一、i2c协议
由飞利浦公司开发,支持设备间的短距离通信。i2c通信需要的引脚少,硬件实现简单、可扩展性强,被广泛应用在系统内多个集成电路(IC)间的通信。
二、i2c物理层
i2c通信总线可连接多个i2c通信设备,支持多个通信主机和多个通信从机。i2c通信只需要两条双向总线——SDA(串行数据线)和SCL(串行时钟线)。
SDA
:用于传输数据SCL
:用于同步数据收发每个连接到总线的设备都有一个独立地址,共7bit,主机正是利用该地址对设备进行访问
i2c支持多主控,任何时间点都只能有一个主控。
i2c器件的SDA引脚和SCL引脚是开漏电路(参照资料)形式,因此,SDA和SCL总线都需要连接上拉电阻(参照资料),当总线空闲时,两条总线均为高电平。
各器件的SDA和SCL信号线在总线上都是
线与
关系。(即连接到总线上的任意器件输出低电平都会将总线信号拉低)
三、i2c协议层
协议层定义了i2c的通信协议。一个完整的i2c数据传输包含开始信号,器件地址,读写控制,器件内访问地址,有效数据,应答信号和结束信号。
1.i2c总线的位传输
数据传输:当SCL位高电平时,SDA必须保持稳定,SDA上传1位数据。
数据改变:当SCL为低电平时,SDA才可以改变电平
i2c位传输时序图
2.i2c总线的开始和结束信号
开始信号
:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。
结束信号
:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。
3.i2c应答信号
- 在
主机
发送完每一个字节数据后,释放SDA(保持高电平),被寻址的接收器在成功接收到每一个字节后,必须产生一个应答ACK
(从机将SDA拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平) - 当
从机
接收不到数据或通信故障时,从机
必须使SDA保持高电平,主机
产生一个结束信号终止传输或者产生新的传输。
4.i2c总线的仲裁机制
- SDA的仲裁也是建立在总线具有
线与
逻辑功能的原理上的。 - 节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。
- SDA的仲裁可以保证i2c总线系统在多个主节点上同时企图控制总线时通信正常进行而且数据不丢失(总线系统通过仲裁只允许一个主节点可以继续占据总线)
- 当SCL为高电平时,仲裁在SDA上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平是
线与
连接。
四、访问i2c总线设备
一般情况下MCU 的I2C 器件都是作为主机和从机通讯,在RT-Thread 中将I2C 主机虚拟为I2C 总线设备,I2C 从机通过I2C 设备接口和I2C 总线通讯,相关接口如下所示:
函数 | 描述 |
---|---|
rt_device_find() | 根据I2C 总线设备名称查找设备获取设备句柄 |
rt_i2c_transfer() | 传输数据 |
五、查找i2c总线设备
在使用I2C 总线设备前需要根据I2C 总线设备名称获取设备句柄,进而才可以操作I2C 总线设备,查找设备函数如下所示,
rt_device_t rt_device_find(const char* name);
参数 | 描述 |
---|---|
name | i2c总线设备名称 |
返回 | – |
设备句柄 | 查找到对应设备将返回相应的设备句柄 |
RT-NULL | 没有找到相应的设备对象 |
一般情况下,注册到系统的I2C 设备名称为i2c0 ,i2c1 等,使用示例如下所示:
|
|
六、数据传输
获取到I2C 总线设备句柄就可以使用rt_i2c_transfer() 进行数据传输。函数原型如下所示:
|
|
参数 | 描述 |
---|---|
bus | i2c总线设备句柄 |
msgs[] | 待传输的消息数组指针 |
num | 消息数组的元素个数 |
返回 | - |
- | - |
消息数组的元素个数 | 成功 |
错误码 | 失败 |
- 和SPI 总线的自定义传输接口一样,I2C 总线的自定义传输接口传输的数据也是以一个消息为单位。
- 参数msgs[] 指向待传输的消息数组,用户可以自定义每条消息的内容,实现I2C 总线所支持的2 种不同的数据传输模式。如果主设备需要发送重复开始条件,则需要发送2 个消息。
!!! note “注意事项” 此函数会调用rt_mutex_take(), 不能在中断服务程序里面调用,会导致assertion报错。
I2C 消息数据结构原型如下:
|
|
- 从机地址addr:支持7 位和10 位二进制地址,需查看不同设备的数据手册。
- 标志flags 可取值为以下宏定义,根据需要可以与其他宏使用位运算“|” 组合起来使用。
!!! note “注意事项” RT-Thread I2C 设备接口使用的从机地址均不包含读写位,读写位控制需修改标志flags。
|
|
使用示例如下所示:
|
|
七、I2C 总线设备使用示例
I2C 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:
- 首先根据I2C 设备名称查找I2C 名称,获取设备句柄,然后初始化aht10 传感器。
- 控制传感器的2 的函数为写传感器寄存器write_reg() 和读传感器寄存器read_regs() 这两个函数分别调用了rt_i2c_transfer() 传输数据。读取温湿度信息的函数read_temp_humi() 则是调用这两个函数完成功能。
|
|