用I/O口模拟IIC总线协议遇到的一些问题
最近做的一个项目,是基于IIC总线通信的传感器系统。由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信。具体的程序在我博客里在先前的早些时候已经贴出来了,如果有兴趣的可以查看我的博客。
主要终结一下我在这个过程中遇见的问题
1、在写完数据(指令或者地址)后 没有应答信号
一般开始的时序根据手册里面的时序图很容易可以写出,第一个没有应答,就有可能向从器件写完数据以后。一般这个时候主要检查的是,上升沿和下降沿,看手册里面说的是上升沿读写还是下降沿读写。我的项目中是上升沿读写数据,换一句话说,在上升沿的时候读写SDA线上的电平指示;下降沿的时候改变数据,其中有一点需要注意,就是先拉低SCL线产生下降沿,在程序中拉低之后要有一定的延时,因为I/O口稳定电平需要一定的时间。不然的话在SDA高的情况下,误拉低了SCL就会产生一个启动条件,自然写入的操作也就失败了。
2、在读取数据的时候数据不对
这样的情况是有数据但是不是有效的数据,一般这个时候就要看模拟的时序是否对了,要明确的在上升沿的时刻读取数据,而后注意的就是数据移位,每读取一位数据之后就要移位一个数据位,下面就是一段读取8位数据的代码。
for(i=0;i<8;i++) { IIC_SCL_HIGH(); //转换完成,SLAVE器件将数据线拉低,时钟线产生上升沿读取高8位数据 REC1=(REC1<<1)+IIC_SDA; delay_us(5); IIC_SCL_LOW(); //将时钟线拉低,等待下一个上升沿的到来 delay_us(5); }
3、在用I/O操作的过程中,高低电平如何书写
输入输出的I/O口都是有方向的,要注意方向的书写,推荐的一种写法就是高电平的写的时候将I/O配置为输入,这样上拉的作用就会向总线输出高电平,这样的好处就是可以在写完之后可以等待从器件对总线的操作,不会产生一定的冲突。下面就是一段高地电平的写法
#define IIC_SCL_HIGH() IIC_SCL_DIR = PORT_INPUT //时钟线拉高 #define IIC_SCL_LOW() IIC_SCL_DIR = PORT_OUTPUT;IIC_SCL=0//时钟线拉低 #define IIC_SDA_HIGH() IIC_SDA_DIR = PORT_INPUT //数据线拉高 #define IIC_SDA_LOW() IIC_SDA_DIR = PORT_OUTPUT;IIC_SDA=0//数据线拉低
原谅我这一生不羁放纵爱自由,也怕有天我会跌倒!