工作的第一个项目,就是关于i2c协议的,之前在学校的时候,用过软件模拟i2c,但是都是模拟i2c主机的,没有接触过模拟从机的。想着应该不会太难吧,不就是操作2根线吗?但是在实际的操作中却让我大吃苦头。下面介绍一下具体的过程吧!
1. I2C总线介绍#
在消费者电子电讯和工业电子中看上去不相关的设计里经常有很多相似的地方例如几乎每个系统都包括:
- 一些智能控制,通常是一个单片的微控制器
- 通用电路,例如LCD驱动、远程I/O口、RAM、EEPROM或数据转换器
- 面向应用的电路,比如音频拨号电话的DTMF发生器等
为了使这些相似之处对系统设计者和器件厂商都得益,而且使硬件效益最大,电路最简单,Philips公司开发了一个简单的双向两线总线,实现有效的IC之间控制。这个总线就成为Inter IC或I2C总线。
下面是I2C总线的一些特征:
- 只要求两条总线线路;一条串行数据线SDA,一条串行时钟线SCL
- 每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器
- 它是一个真正的多主机总线,如果两个或更多主机同时初始化数据传输可以通过冲突检测和仲裁防止数据被破坏
- 串行的8位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s
- 片上的滤波器可以滤去总线数据线上的毛刺波,保证数据完整
- 连接到相同总线的IC数量只受到总线的最大电容400pF限制
2. I2C硬件接口#
I2C一共有2根线:SCL时钟线、SDA数据线。
其标准的与从机设备连接的图片如图所示:
从图中可以看到,i2c的SCL和SDA都通过上拉电阻连接到+VDD,而连接在总线上的器件采用开漏输出的方式,该方式只能输出低电平,浮空状态为高阻态,必须通过外部的上拉电阻把总线电平拉高,所以i2c总线空闲时,总线电平为高电平。
3. I2C协议介绍#
I2C的协议,说白了就是规定数据如何传输的,其时序图如下图所示。
从上图中可以看到I2C通讯中关键的几点:
- 在SCL高电平时,SDA出现下降沿,即为I2C的start信号。可以理解为跳入坑中,开始通信。
- 在数据传输中,SDA线上的数据在SCL为高电平时必须保持稳定,只有在SCL为低电平时,SDA线上的数据才允许改变。
- 发送到SDA线上的每个字节必须为8位,首先传输的是数据的最高位(MSB)。
- 在主机向从机发送地址时,若是该地址和从机地址相同,则从机应拉低SDA总线,发送ACK信号。
- 在SCL为高电平时,SDA出现上升沿,即为I2C的STOP信号。可以理解为跳出坑外,停止通信。
- SCL信号是有主机控制的,SDA的控制权由主机和从机分时控制。
理解了以上几点,那么I2C的通讯协议基本是掌握了。下面这两幅图是I2C主机写从机和读从机的总线控制的示意图。
第一幅图为主机向从机写数据的总线控制示意图,写数据时,传输方向未发生变化。
第二幅图为主机读从机数据的总线控制示意图,在读数据时,主机先向从机发送地址,然后从机向主机发送数据,传输方向发生变化。
4. I2C从机软件实现思路#
在使用STM32模拟I2C从机时,查阅了很多关于模拟从机的资料,很多人说使用中断的方式可能无法采集高速I2C通信时的SCL信号,但是我在TI的一个文档中找到了使用软件模拟I2C从机即是使用中断实现的,TI使用两块MSP430单片机,一块作为I2C的主机,另一块作为从机。TI在设计文档中这么写道:
In the software slave I2C example code, MCLK frequency is set at 8 MHz. With 8-MHz MCLK, software slave I2C can achieve 100-kHz SCL clock frequency using assembly code and 43-kHz SCL clock frequency using C code. Higher SCL clock frequency can be achieved with higher frequency MCLK. The FRAM memory size for the C code and the assembly code is different.
即以8MHZ的主时钟,以汇编写得到代码,从机可以实现100kHZ的SCL时钟频率,以C语言写的代码,可以实现43KHZ的SCL时钟频率。
所以,对于72MHZ时钟频率的STM32单片机来说,使用中断应该可以实现快速的I2C通讯。下面就介绍一下TI使用中断实现软件模拟I2C从机的思路。
首先,TI使用了SDA和SCL两个中断,在中断中又使用状态机的方法,实现对I2C通信状态的分解。
SDA中断 | 判断START状态和STOP状态 |
---|---|
SCL中断 | 根据SCL上升沿和下降沿中断,进入I2C_State下,处理不同的任务 |
其分为14个不同的状态,下图为其14个状态及每种状态的描述。
这14个状态把I2C通讯的发送、接收等各种情况全部包括,构成了一个状态机。
这样的实现比较复杂,代码逻辑也比较繁琐,但是它包含了i2c通信的各种情况,相对其他的实现方式,相对较好。
5. I2C从机代码#
1 | //iicslave.c |
1 |
|
参考内容:
- STM32-IIC从模式
- 森.烂笔头的博客
- TI公司:slaa703a.pdf
- 周立功:I2C总线规范