You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

STM32(F0)与24LC16B EEPROM I2C通信失败求助(Arduino可正常工作)

分析STM32F0读取24LC16B EEPROM出现NACK的问题

嘿,我来帮你拆解下这个问题!既然Arduino测试完全正常,说明硬件接线和EEPROM本身没毛病,问题肯定出在STM32的I2C配置或者代码逻辑上,我整理了几个最可能的原因和解决思路:

1. 代码逻辑的核心错误:没发内存地址就终止传输

你的测试函数里,发起写传输时声明要发2字节,但实际上啥数据都没发(比如关键的EEPROM内存地址)就直接调用了停止指令。24LC16B的通信规则很明确:

  • 读数据前,必须先通过写传输告诉它要读的内存地址(这是11位地址,要拆成两部分:高3位拼在设备地址的最后3位,低8位作为单独的字节发送)
  • 你现在的代码只发了设备地址0xA2,之后直接停了,EEPROM根本搞不懂你要干嘛,自然会返回NACK。

给你一个正确的读操作流程参考:

uint8_t readEEPROMData(uint16_t memAddress){ 
    // 第一步:发送设备写地址 + 内存地址低8位
    // 设备写地址 = 0xA0 | ((memAddress >> 8) & 0x07) << 1 (高3位是块地址)
    uint16_t deviceWriteAddr = 0xA0 | ((memAddress >> 8) & 0x07) << 1;
    I2C_TransferHandling(I2C1, deviceWriteAddr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
    
    // 等待发送寄存器空,写入内存地址低8位
    while(!(I2C1->ISR & I2C_ISR_TXIS));
    I2C1->TXDR = (uint8_t)memAddress;
    
    // 等待写传输完成
    while(!(I2C1->ISR & I2C_ISR_TC));

    // 第二步:重复起始,发送设备读地址,准备接收1字节数据
    uint16_t deviceReadAddr = deviceWriteAddr | 0x01; // 读地址是写地址+1
    I2C_TransferHandling(I2C1, deviceReadAddr, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
    
    // 等待接收数据
    while(!(I2C1->ISR & I2C_ISR_RXNE));
    uint8_t data = I2C1->RXDR;
    
    return data;
}

2. STM32 I2C初始化的潜在坑

2.1 引脚配置必须是复用开漏

STM32的I2C引脚(比如PB6/SCL、PB7/SDA)一定要配置成复用开漏输出,而且必须带上拉电阻(建议用外部10kΩ的,内部上拉驱动能力弱,容易出问题)。要是你配置成推挽输出,I2C总线电平会乱套,EEPROM直接不响应,返回NACK。

检查你的引脚初始化代码,确保模式是GPIO_MODE_AF_OD,并且选对了对应的复用功能(比如I2C1的复用功能编号是4,不同引脚可能有差异,查下STM32F0的 datasheet)。

2.2 I2C时钟配置不能错

24LC16B支持最高400kHz的快速模式,但STM32的I2C时序配置必须严格符合要求:

  • 首先,I2C外设的时钟来自APB1,必须是SCL频率的整数倍。比如APB1是48MHz,要跑100kHz的标准模式,CCR寄存器的值得是48000000 / (2 * 100000) = 240;如果是400kHz快速模式,CCR要设成60。
  • 要是时钟配置错了,SCL频率太高或者时序不匹配,EEPROM会直接拒绝响应,给你NACK。

另外,STM32F0用TIMINGR寄存器配置I2C时序,里面的上升/下降时间参数也要符合24LC16B datasheet的要求,别瞎填。

2.3 BUSY标志的等待逻辑搞反了吗?

你代码里的I2C_WaitForFlag(I2C_ISR_BUSY);,得确认这个函数是等BUSY标志清零(也就是总线空闲),而不是等它置1。要是逻辑反了,在总线忙的时候硬发起传输,肯定失败。

3. 容易忽略的细节问题

  • ACK功能要开:初始化I2C的时候,记得开启ACK响应(设置I2C_CR1ACK位)。虽然写传输时是EEPROM给STM32发ACK,但如果STM32的ACK配置不对,可能会误把EEPROM的ACK当成NACK,导致判断错误。
  • 电源要稳:虽然Arduino测着没问题,但STM32的电源波动可能影响I2C总线电平,确保EEPROM的VCC在2.5V~5.5V的范围内,别掉电压。

内容的提问来源于stack exchange,提问作者Mathlight

火山引擎 最新活动