在之前一直使用原子的模拟iic在各种stm32单片机上用时没有过这种情况,这次在PIC单片机上使用时出现了这个问题。无论如何读写都是0xff。在经过多天排查之后最终发现是问题在原子的demo的iic.c里面的发送启动和结束信号的时序导致的。先贴原子代码如下:
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
我们可以看到在发送启动信号的时候SDA和SCL同时置高或者置低。虽然有先后顺序,但是单片机如果在翻转电平时速度不够或者有其它原因导致的电平不稳这就使得发送的启动和结束信号不对;
逻辑分析仪如下:不好意思,图丢了,我描述一下吧
启动信号的时候必须要保证scl拉高之前SDA复位到高电平了,确保在SCL高电平时只有下降沿,所以说尽量让他们时间上有个明显的先后,否则可能SCL一旦高就将不稳定的SDA当成了一个启动或者别的指令。所以修改代码如下:
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SCL=0;
delay_us(1);
IIC_SDA=1;
delay_us(1);
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
delay_us(1);
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
delay_us(4);
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
https://blog.csdn.net/pamzerbhu/article/details/79949684解决问题之后的逻辑分析仪波形如下:写入
读取
如有其它问题可以评论留言