本帖最后由 stayhungry 于 2016-10-10 15:27 编辑
这几天做的一个项目,需要用到两块STM32之间的I2C通讯。
网上查了一堆,大多数只有STM32作主机操作FLASH什么的(软件模拟和硬件都有,不过硬件作主机有人说BUG,我没深入研究),很少有用STM32作为从机,所以在做的时候也遇到一些问题。这里我就分享一下,STM32主机用IO模拟I2C,从机使用STM32本身的硬件I2C的一些见解。
PS:我是用原子的最简模板和I2C驱动(有一些小改动),做了两个工程,在附件里面,跑系统也能用。读从机和写从机功能都写了,大家可以通过用/**/注释来进行选择。
例如:主机程序中的“read”段对应从机程序中的“1”段,主机程序中的“write”段对应从机程序中“0”段。
有什么想不清楚的就读一下这个地方:
主机读从机,从机需要发送数据:
1、通过一字节地址(7位地址+1位R/W)控制读从机还是写从机,STM32在这个地方遵循标准I2C协议。
2、STM32能够识别NACK和ACK(网上有的说不能识别NACK,然后什么需要加发一个无用数据什么的,我没遇到这种问题)。
在收到NACK后,是不能响应STOP指令的,STM32F10X参考手册说的(经过自己验证的确如此),所以用户使用STM32作从机时候自己写的协议与标准I2C协议有出入,因为I2C标准协议是收到NACK后,等待主机再发送一个STOP指令结束通信。
解决办法:
(1)从机收到NACK后,硬件会自动关闭这次的通信,所以可以减少等待STOP指令这一步骤(因为已经自动结束这次通信了,所以不需要STOP也不会响应STOP)。
(2)主机不发送NACK,只发送ACK,主机收完最后一个数据后,直接发送STOP指令,强行中断通信,启动新一次通信。
(3)只发送ACK,发完之后,直接重新初始化从机硬件I2C,启动一次全新的通信。
经实验验证,第1种方法更加简单,而且稳定,若是出现传输数据错误,很有可能是因为没接外部上拉。第3种也非常稳定,就是这样配置感觉非常不合理。
3、STM32从机的发送时序是主机控制的(经过验证)
STM32F10X参考手册上对DR寄存器的描述是,当给从机发送器DR赋值时,从机发送器"自动启动数据传输",让人误以为从机获得了数据总线的控制权和时钟线控制权,自主发送,违背了I2C标准协议。而实际现象是给从机发送器DR赋值之后,从机进入“准备状态”,仍然在等待主机的时钟,主机每给一个时钟,从机发送一次数据。(我是通过更改IIC_Read_Byte里面的时钟脉冲时间来验证的)。
4、在主机发送完地址给从机之后,必须delay一段时间,因为从机处理地址(R/W)位时候需要时间(我是从网上看到的说法,忘记在哪了,实测不加delay会崩)。
5、每次主机读取一字节数据时候,必须delay一段时间,delay时间的长短取决于从机发送数据之后需要做多少东西,遵循主机在读取下一个字节数据时候,从机必须处于在while( !I2C_CheckEvent(I2C1,I2C_EVENT_SLAVE_BYTE_TRANSMITTED ));里面。否则,传输数据出错。
主机写从机,从机需要接收数据:
1、每次主机写一字节数据时候,必须delay一段时间,delay时间的长短取决于从机接收数据之后需要做多少东西,遵循主机在写下一个字节数据时候,从机必须处于在while( !I2C_CheckEvent(I2C1,I2C_EVENT_SLAVE_BYTE_RECEIVED ));里面。否则,传输数据出错。
追更:当使用硬件I2C的时候,记得使用外部上拉,记得使用外部上拉,记得使用外部上拉。
上面都是些个人见解和心得,如有错误地方还望指出,同时想问一个问题。
在开发中,经常会遇到参考手册和数据手册没有说明的问题,然后之前有见到一些前辈会参考一些官方英文手册,部分内容有类似于对一个寄存器的某个标志位有更加深入的解释,这种类型的手册叫什么东西?我应该在官网的哪些地方能找到呢?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
谢谢:我还遇到了一个问题,需要加将近10ms的延时。我猜测我是不是哪里没有配置好
http://www.openedv.com/thread-95872-1-1.html
一周热门 更多>