24LC512 I2C块读取异常:read_i2c_block_data从第2个存储地址起始读取
解决24LC512 I2C块读取从第2个地址开始的问题
这问题我之前帮朋友排查过,核心是24LC512的16位地址机制和Python I2C库默认函数的行为不匹配,咱们一步步理清楚:
问题根源
24LC512是64KB的EEPROM,需要16位存储地址才能覆盖所有单元,但很多基础I2C库(比如smbus)的read_i2c_block_data函数默认只发送8位的寄存器地址参数。当你调用bus.read_i2c_block_data(0x54, 0, length)时,实际只给芯片传了低8位地址0x00,高8位地址要么残留了之前的数值,要么被芯片默认解析成了非0值,导致地址指针没正确指向0x0000,最终块读取从0x0001开始。
而read_byte能正常工作,是因为你之前用write_byte_data(0x54, 0, 0)已经把地址指针设到了0x0000(这里虽然只传了8位地址,但24LC512会默认高8位为0),之后的read_byte是基于当前指针读,读完自动自增,所以行为符合预期。
解决方案
要正确读取24LC512的块数据,必须先完整发送16位地址,再执行块读取,这里给两种可行方法:
方法1:用i2c_rdwr发送完整I2C消息(推荐)
如果你的库支持i2c_rdwr(比如smbus2),可以构造包含地址写入和数据读取的完整传输:
from smbus2 import SMBus, i2c_msg # 初始化总线,根据你的硬件调整总线号 bus = SMBus(1) device_addr = 0x54 read_length = 10 # 按需修改要读取的字节数 # 构造写地址消息:设备写地址 + 16位地址(高8位在前,低8位在后) write_addr_msg = i2c_msg.write(device_addr, [0x00, 0x00]) # 构造读数据消息 read_data_msg = i2c_msg.read(device_addr, read_length) # 执行组合传输 bus.i2c_rdwr(write_addr_msg, read_data_msg) # 解析结果 data = list(read_data_msg) print(data)
方法2:先通过write_i2c_block_data设置完整地址
如果只能用基础smbus函数,可以先发送两个字节的地址定位到0x0000,再读块:
# 先写入16位地址(高8位0x00,低8位0x00) bus.write_i2c_block_data(device_addr, 0x00, [0x00]) # 再执行块读取 data = bus.read_i2c_block_data(device_addr, 0x00, read_length)
这里的write_i2c_block_data相当于给芯片依次传了高8位和低8位地址,完成16位地址的定位。
额外验证点
- 47C16是16Kbit的EERAM,只需要14位地址,8位地址参数足够覆盖,所以它不会出现这个问题;
- 检查硬件:确认SDA/SCL的上拉电阻正常,避免信号干扰导致地址解析错误。
内容的提问来源于stack exchange,提问作者Kurt
相关产品推荐
相关产品推荐

