
实现I2C从设备驱动需按初始化(配置时钟、10位地址)、数据传输(处理R/W位、应答位、传感器时序)、错误检测(超时、NACK)的流程,通过硬件仲裁解决总线竞争,确保数据可靠传输。
I2C从设备的核心流程围绕“地址匹配”“数据传输”“时钟同步”和“错误处理”展开:
类比:传感器作为“从设备”,主控制器(主设备)通过地址(如0x10A)呼叫它,传感器收到后回应ACK,主控制器发送数据(写)或接收数据(读),若传感器没回应(NACK),主控制器重发。总线竞争时,多个主控制器同时呼叫,优先级高的继续,低优先级的等待。
| 特性 | I2C从设备(多主多从) | SPI从设备(主从) |
|---|---|---|
| 地址配置 | 10位地址(7位+引脚位A2-A0),可冲突 | 从设备地址固定,由主设备控制 |
| 总线竞争 | 硬件仲裁(SCL电平比较优先级) | 无,主设备独占总线 |
| 数据传输 | 串行,双向,应答位确认 | 串行,全双工,时钟由主设备控制 |
| 应用场景 | 低速传感器(温度、光强,转换时间较长) | 高速存储器、显示驱动(高速) |
| 注意点 | 需配置引脚位避免地址冲突 | 无需额外地址配置,传输速率高 |
// 1. 初始化I2C从设备(10位地址扩展,假设STM32)
void i2c_slave_init() {
I2C1->CR1 |= I2C_CR1_SDAEN; // 使能SDA
I2C1->CR1 &= ~I2C_CR1_SCEEN; // 禁止SCL
I2C1->CR1 |= I2C_CR1_TEN; // 使能从模式
I2C1->OAR1 = (0x10 << 1); // 7位地址0x10,扩展为10位
I2C1->OAR2 = 0b000; // A2-A0=0,地址为0x10A
I2C1->CR1 |= I2C_CR1_SPEED; // 设置标准速度(100kHz)
}
// 2. 处理I2C中断(主设备发起通信)
void i2c_slave_isr() {
uint8_t addr = I2C1->OAR2; // 读取带R/W位的地址
if (addr & 0x01) { // R/W位=1:主设备读
wait_sensor_conversion(10); // 等待传感器转换(10ms)
uint8_t data = read_sensor_data(); // 读取温度/光强
I2C1->DR = data; // 发送数据
I2C1->CR1 |= I2C_CR1_ACK; // 发送ACK
} else { // R/W位=0:主设备写
uint8_t data = I2C1->DR; // 读取主设备数据
write_register(data); // 写入寄存器(配置传感器)
I2C1->CR1 |= I2C_CR1_ACK; // 发送ACK
}
// 3. 错误检测(超时+NACK)
if (i2c_check_error()) {
handle_error(); // 重试逻辑(最多3次)
}
}
// 4. 错误检测函数(超时+NACK)
bool i2c_check_error() {
return I2C1->SR2 & I2C_SR2_BERR // 总线错误
|| I2C1->SR2 & I2C_SR2_TIMEOUT; // 超时
}
// 5. 总线竞争仲裁(硬件仲裁)
void handle_bus_arbitration() {
if (I2C1->SR2 & I2C_SR2_SMBusArbit) { // 检测仲裁丢失
i2c_wait_bus_free(); // 等待总线空闲,重新初始化
}
}
// 6. 超时重试逻辑
void handle_timeout() {
if (retry_count < 3) {
retry_count++;
i2c_slave_init(); // 重新初始化
} else {
// 报警或系统复位
}
}
“实现I2C从设备驱动,核心是按流程完成初始化、地址配置、数据传输(含应答位和传感器时序)、错误检测,并处理总线竞争。首先,初始化阶段,配置I2C时钟(如100kHz),使能从模式,通过引脚位(A2-A0)扩展10位地址(如0x10A,7位地址0x10 + 引脚位0)。然后,主设备发起通信时,从设备检测地址匹配,发送ACK。如果是读操作(R/W=1),从设备等待传感器转换完成(如10ms),读取数据并发送,主设备确认;如果是写操作(R/W=0),从设备接收数据并写入寄存器,确认。错误检测包括检查总线空闲、NACK(数据未接收)和超时(如通信超时则重试)。总线竞争时,I2C通过硬件仲裁,优先级高的主设备继续传输,低优先级的等待;时钟同步通过SCL线电平变化同步所有设备。总结来说,从设备驱动需严格遵循I2C协议时序,处理地址、应答、数据传输和错误,通过仲裁和时钟同步保证可靠性。”