2. I2C协议基础:7位与10位寻址模式、读写操作位、ACK/NACK机制

I2C(Inter-Integrated Circuit)总线是一种由Philips(现NXP)开发的两线式串行通信协议,广泛应用于嵌入式系统中连接微控制器与外围设备(如传感器、EEPROM、ADC/DAC、IO扩展芯片等)。在QNX I2C驱动开发中,深刻理解协议层的寻址模式、读写控制与应答机制是正确配置通信接口参数、定位总线故障的前提。

2.1 7位与10位寻址模式

I2C总线上的每个从设备都有一个唯一的地址。标准模式支持7位地址,最多可挂载112个节点(保留地址除外);扩展模式支持10位地址,允许更多设备共存。QNX的I2C驱动接口(如 i2c_open()、i2c_read()、i2c_write())通过标志位区分两种寻址模式。

2.1.1 7位寻址

  • 地址范围:0x00 ~ 0x7F(其中0x00为通用呼叫地址,0x01~0x07为保留地址,实际可用0x08~0x77)。
  • 传输格式:主设备发送起始条件后,先发送7位从机地址 + 1位读写位(R/W),共8位。
  • 典型应用:大多数I2C传感器(如温度传感器TMP102、加速度计MPU6050)使用7位地址。
QNX驱动配置要点:在 i2c_send() 或 i2c_recv() 的参数中,地址字段直接填入7位地址(左对齐,高7位有效),驱动内部会自动左移1位并拼接读写位。

2.1.2 10位寻址

  • 地址范围:0x00 ~ 0x3FF(10位地址空间)。
  • 传输格式:分两阶段发送。第一阶段:11110XX + R/W(其中XX为10位地址的高2位);第二阶段:发送剩余8位地址。
  • 兼容性:10位寻址设备可与7位设备共存于同一总线,但主设备必须支持10位寻址模式。
7位与10位寻址模式对比
对比项 7位寻址 10位寻址
地址位数 7 bit 10 bit
最大设备数 112(扣除保留地址) 1024
首字节格式 AAAAAAA + R/W 11110AA + R/W(AA为高2位)
传输字节数 1字节地址 + 数据 2字节地址 + 数据
QNX驱动标志 I2C_ADDR_7BIT I2C_ADDR_10BIT
开发建议:在QNX Resource Manager(资源管理器)中实现I2C驱动时,务必在 i2c_iofunc_attr_t 结构体中正确设置 addr_mode 字段。错误配置将导致地址无法被从设备识别,产生NACK响应。
I2C 7位与10位寻址传输格式对比 7位寻址传输序列 S 7位地址 (A6~A0) R/W ACK 数据... 10位寻址传输序列 S 11110 + A9~A8 R/W ACK1 A7~A0 ACK2

2.2 读写操作位(R/W)

I2C通信中,每个地址字节的最低位(LSB)为读写控制位:

  • R/W = 0:表示主设备将要写入数据到从设备(写操作)。
  • R/W = 1:表示主设备将要读取从设备的数据(读操作)。

在QNX I2C驱动中,读写操作通常通过不同的API函数或标志位来区分:

QNX I2C读写操作API对比
操作类型 QNX API函数 R/W位值 数据方向
写操作 i2c_write() / i2c_send() 0 主设备 → 从设备
读操作 i2c_read() / i2c_recv() 1 从设备 → 主设备
复合操作 i2c_write_read()(先写寄存器地址再读数据) 0 → 1(重复起始条件) 双向
常见故障点:在QNX驱动中,如果 i2c_write() 调用后未等待从设备内部处理完成(如EEPROM写入周期),紧接着调用 i2c_read() 可能导致总线冲突或数据错误。建议在写操作后加入适当延时或轮询从设备状态。

2.3 ACK/NACK机制

I2C总线使用应答(ACK)和非应答(NACK)机制来确保数据可靠传输。每个字节(包括地址字节和数据字节)传输完成后,接收方必须在第9个SCL时钟周期内拉低SDA线表示ACK,或保持高电平表示NACK。

2.3.1 应答规则

  • 地址字节应答:从设备在收到匹配的地址后,必须发送ACK。如果总线上没有设备响应此地址,SDA保持高电平(NACK),主设备应发送停止条件终止传输。
  • 数据字节应答:
    • 写操作:从设备每收到一个数据字节后发送ACK。
    • 读操作:主设备每收到一个数据字节后发送ACK;当主设备希望停止读取时,发送NACK并随后发送停止条件。

2.3.2 QNX驱动中的ACK/NACK处理

QNX I2C驱动框架在底层硬件抽象层(HAL)中处理ACK/NACK检测。驱动开发者需要关注以下状态:

/* QNX I2C驱动返回状态示例 */
#define I2C_STATUS_OK       0   /* 传输成功,收到ACK */
#define I2C_STATUS_NACK_ADDR -1 /* 地址NACK:无设备响应 */
#define I2C_STATUS_NACK_DATA -2 /* 数据NACK:从设备拒绝数据 */
#define I2C_STATUS_ARB_LOST  -3 /* 仲裁丢失 */
故障排查要点:当QNX I2C驱动返回 I2C_STATUS_NACK_ADDR 时,应检查:① 从设备地址是否正确(7位/10位模式匹配);② 从设备是否上电并处于正常工作状态;③ 总线SCL/SDA电平是否被异常拉低(总线锁死)。返回 I2C_STATUS_NACK_DATA 时,通常表示从设备不支持当前操作(如写保护、寄存器不存在)。
I2C ACK/NACK 应答时序与QNX驱动状态机 主设备发送地址 等待ACK/NACK ACK → 继续传输 传输数据 NACK → 发送停止条件 返回错误状态码 QNX驱动状态:I2C_STATUS_OK(ACK) / I2C_STATUS_NACK_ADDR(地址NACK) / I2C_STATUS_NACK_DATA(数据NACK)

2.4 本章小结

  • 7位寻址是I2C最常用的模式,地址范围0x08~0x77,QNX驱动默认使用此模式。
  • 10位寻址用于需要更多从设备的场景,需在QNX驱动中显式设置 I2C_ADDR_10BIT 标志。
  • 读写位(R/W)控制数据方向,QNX通过 i2c_write() 和 i2c_read() 等API封装了底层位操作。
  • ACK/NACK机制是I2C总线可靠性的核心,QNX驱动返回的状态码直接反映应答结果,是故障排查的第一手信息。