51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

在嵌入式系统中实现一个I2C从设备驱动,用于读取光学传感器的温度和光强数据。请描述从初始化、地址配置、数据传输(包括应答位处理)到错误检测的完整流程,并说明如何处理总线竞争或时钟同步问题。

识光芯科嵌入式实习生难度:中等

答案

1) 【一句话结论】

实现I2C从设备驱动需按初始化(配置时钟、10位地址)、数据传输(处理R/W位、应答位、传感器时序)、错误检测(超时、NACK)的流程,通过硬件仲裁解决总线竞争,确保数据可靠传输。

2) 【原理/概念讲解】

I2C从设备的核心流程围绕“地址匹配”“数据传输”“时钟同步”和“错误处理”展开:

  • 从设备地址(10位扩展):由7位地址(如0x10)+引脚位(A2-A0)组成,通过硬件引脚电平(如A2-A0=0)扩展为0x10A,主设备通过该地址识别从设备。
  • 应答位(ACK/NACK):从设备收到数据后,通过SCL线发送低电平(ACK,表示数据接收成功)或高电平(NACK,表示数据未接收或错误),主设备根据应答位判断传输是否成功。具体时序:SCL为高时,SDA拉低为ACK;保持高为NACK。
  • 时钟同步:SCL线的电平变化(高→低→高→低)同步所有设备时序,确保数据传输的时序一致性。
  • 总线竞争:当多个主设备同时传输时,通过硬件仲裁(比较SCL线电平),优先级高的主设备继续传输,低优先级的释放总线。

类比:传感器作为“从设备”,主控制器(主设备)通过地址(如0x10A)呼叫它,传感器收到后回应ACK,主控制器发送数据(写)或接收数据(读),若传感器没回应(NACK),主控制器重发。总线竞争时,多个主控制器同时呼叫,优先级高的继续,低优先级的等待。

3) 【对比与适用场景】

特性I2C从设备(多主多从)SPI从设备(主从)
地址配置10位地址(7位+引脚位A2-A0),可冲突从设备地址固定,由主设备控制
总线竞争硬件仲裁(SCL电平比较优先级)无,主设备独占总线
数据传输串行,双向,应答位确认串行,全双工,时钟由主设备控制
应用场景低速传感器(温度、光强,转换时间较长)高速存储器、显示驱动(高速)
注意点需配置引脚位避免地址冲突无需额外地址配置,传输速率高

4) 【示例】(伪代码,含寄存器配置与传感器时序)

// 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 {
        // 报警或系统复位
    }
}

5) 【面试口播版答案】(约90秒)

“实现I2C从设备驱动,核心是按流程完成初始化、地址配置、数据传输(含应答位和传感器时序)、错误检测,并处理总线竞争。首先,初始化阶段,配置I2C时钟(如100kHz),使能从模式,通过引脚位(A2-A0)扩展10位地址(如0x10A,7位地址0x10 + 引脚位0)。然后,主设备发起通信时,从设备检测地址匹配,发送ACK。如果是读操作(R/W=1),从设备等待传感器转换完成(如10ms),读取数据并发送,主设备确认;如果是写操作(R/W=0),从设备接收数据并写入寄存器,确认。错误检测包括检查总线空闲、NACK(数据未接收)和超时(如通信超时则重试)。总线竞争时,I2C通过硬件仲裁,优先级高的主设备继续传输,低优先级的等待;时钟同步通过SCL线电平变化同步所有设备。总结来说,从设备驱动需严格遵循I2C协议时序,处理地址、应答、数据传输和错误,通过仲裁和时钟同步保证可靠性。”

6) 【追问清单】

  1. 问:10位地址的引脚位(A2-A0)如何具体配置?
    答:根据传感器数据手册,通过硬件引脚(如A2、A1、A0)拉低或拉高,配置为0b000,使从设备地址扩展为0x10A(7位地址0x10 + 引脚位0)。
  2. 问:传感器转换时间(如10ms)如何适配数据传输速率?
    答:根据传感器手册的转换时间,调整I2C时钟频率(如降低为50kHz),确保数据传输在转换完成后进行,避免数据错误。
  3. 问:超时检测的具体阈值(如T_timeout=100ms)如何设定?
    答:根据通信延迟和系统响应时间,设定超时阈值(如100ms),若通信超时则触发重试逻辑(最多3次)。
  4. 问:总线竞争仲裁中,低优先级设备如何释放总线?
    答:通过硬件电路检测SCL被拉低(其他主设备传输),低优先级设备释放SCL/SDA,等待总线空闲后重新初始化。
  5. 问:应答位(ACK/NACK)如何处理?
    答:从设备收到数据后,若数据正确,发送ACK(SCL为高时SDA拉低);若数据错误或未准备好,发送NACK(SCL为高时SDA保持高),主设备根据NACK重发。

7) 【常见坑/雷区】

  1. 地址配置错误:引脚位设置错误导致地址冲突,主设备无法找到从设备(需确认引脚电平)。
  2. 传感器时序适配不当:数据传输速率过快,超过传感器转换时间,导致数据错误(需根据手册调整时钟频率)。
  3. 超时检测遗漏:未检查通信超时,导致主设备持续发送数据,从设备无响应(需设置超时阈值和重试逻辑)。
  4. 总线竞争处理不当:未实现仲裁机制,多个主设备竞争时通信失败(需硬件仲裁或软件优先级控制)。
  5. 应答位处理错误:发送NACK但误判为ACK,导致数据传输中断(需正确检测SCL高时的SDA电平)。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1