I2C链接多个设备

I2C的特点
I2C( Inter-Integrated Circuit )总线是一种由飞利浦(现在的恩智浦 NXP )公司在 1980 年代初开发的一种串行、同步、半双工的通信总线协议,主要用于设备短距离之间的低速传输。
- 两线制:这是 I2C 最显著的特点,只需要两根信号线(时钟线和数据线)即可实现通信。
- SCL:时钟线,由主设备产生,用于同步数据传输。
- SDA:双向数据线,用于传输数据(地址和数据位)。
- 多主机 / 多从机 :一条总线上可以连接多个主设备(Master)和多个从设备(Slave),主设备发起通信,从设备响应。但绝大多数实际应用都只有 1 个主机。
- 我们把主动发起通信的主机,叫做 Master,被动响应通信的主机,叫做 Slave
- 设备地址:每个从设备都有一个唯一的 7 位或 10 位地址,主设备通过地址来选择要与哪个从设备通信。通常都是 7 位地址,10 位地址比较罕见。
- 同步串行通信:所有数据传输都由 SCL 时钟信号同步,数据位在 SCL 的高电平(或上升沿)期间进行采样
- 半双工:同一时刻,数据只能在一个方向上传输(要么主发从收,要么从发主收)。
- 速度模式:定义了多种标准速度模式:
标准模式(Standard Mode):100 kbps
快速模式(Fast Mode):400 kbps
快速模式 +(Fast Mode Plus):1 Mbps(stm32F103ZET6 不支持)
I2C的应用十分广泛

- 如上图中 ① 是温湿度 + 气压传感器。
- 如上图中 ② 是 3 轴加速度计 + 3 轴陀螺仪传感器。手机的自动旋转屏幕、AR 导航、防抖摄影、体感游戏等都需要依赖这类器件实现。
- 如上图中 ③ 是环境光传感器,用于测量光照强度。
- 如上图中 ④ 是摄像头模组,摄像头的配置接口通常都是 I2C 接口。
- 如上图中 ⑤ 是心率、血氧传感器,各种手表、手环都是依赖这类传感器实现心率、血氧浓度监测的。
- 如上图中 ⑥ 是小尺寸显示屏。
- 如上图中 ⑦ 是 ToF 传感器,这是基于光 "飞行时间 (Time of Flight)" 计算距离的传感器。
- 如上图中 ⑧ 是 RTC 模块,一些不带 RTC 外设的主控方案都会使用外置 RTC 芯片方案
所以老铁们请务必学好
所以为什么会存在 I2C 呢?
- 支持 1 对多通信,从而支持读写多种传感器或者模块数据
- 用最少的物理连接,实现芯片间简单、高效的板级通信
I2C与GPIO的关系
其实与USART与GPIO的关系差不多,如下图。

I2C复用哪个GPIO由意法半导体决定
如下图的数据手册,在一般情况之下,I2C2会复用PB10和PB11引脚,但是PB10和PB11可以被多个片上外设复用,所以当PB10和PB11被其他片上外设复用时,会启用重定义功能,让I2C2复用其他引脚。

I2C的输出模式
I2C规定:

I2C复用GPIO的简化图
无用的地方将其遮盖

再简化一下

I2C输出数据
输出 1 或者高电平
- 如果我们想让 SDA pin 输出高电平,只要保持 N-MOS 断开,那么 SDA 线默认就会在上拉 Vdd 的拉动下,自动保持高电平
输出 0 或者低电平
- 如果我们想让 SDA pin 输出低电平,只要保持 N-MOS 闭合,那么 SDA 线就会接地,输出低电平。

I2C输入数据
和输出数据使用的是同一个引脚,为什么可以这样?
理解 I2C 输出时 / 不输出时,还能感知到数据变化
"引脚的功能配置" 和 "引脚内部的硬件电路" 是不同的,从配置角度,一个引脚确实只能选择一种工作模式,但是从硬件角度,它的连接就是客观存在,虽然没有配置输入,但是它是能感知到外部数据变化的。
如下图,输出和输入是并联在一起的。

SCL时钟与输入输出
就一句话,在I2C通信中,一般由主设备产生时钟信息,也只能由主设备master产生时钟信息。
时钟与数据
I2C 规定:
- 在 SCL 时钟线为高的时候,SDA 数据线上的数据,必须稳定不变
- 在 SCL 时钟线为低的时候,SDA 数据线上的数据,才允许变化 (从高到低,或者从低到高,当然不变也行)

数据采集
所以接收方在时钟为上升沿或下降沿时采集数据,就能正确地采集到数据。
为什么呢?看看下面这个图,SCL高电平时的对应此时SDA的高电平是更为窄的。
