如何将基于I2C的EEPROM写入C宏改写为Python实现
C代码逻辑解析
你提供的C宏是一个通用的EEPROM写入工具,核心逻辑是绕过C的类型限制,把任意类型的变量按原始字节写入EEPROM,不需要针对不同类型单独写适配代码,具体执行步骤如下:
- 先取变量
p的内存首地址,强制转为字节指针pp,这样就可以按字节为单位读取变量的全部内存内容 - 遍历变量
p占用的所有内存字节,遍历次数等于sizeof(p),也就是该类型变量占用的内存字节数 - 从传入的EEPROM起始地址
address开始,依次将每个字节写入对应偏移的EEPROM地址,完成整块数据的写入
如果你的硬件是用外接I2C接口的EEPROM芯片(比如AT24C系列),确实是用machine模块的I2C对象实现;如果你的开发板(比如部分AVR、ESP系列)固件自带模拟EEPROM支持,可以直接调用封装好的EEPROM接口,不用手动操作I2C。
MicroPython 实现代码
Python是高级语言,不能直接读取变量的原始内存地址,所以需要先把目标数据转为字节序列,再执行写入,和C代码的最终效果完全一致。
情况1:使用固件自带的内置EEPROM接口
from machine import EEPROM import struct # 初始化EEPROM,size参数根据你的硬件可写空间调整,比如ESP32一般最大支持4096字节 eeprom = EEPROM(size=4096) def eeprom_write(address, data): # 把输入数据转为字节序列 if isinstance(data, int): # 假设对应C的4字节有符号int,小端序,可根据你的实际C环境调整长度和端序 data_bytes = data.to_bytes(4, byteorder='little', signed=True) elif isinstance(data, float): # 对应C的4字节单精度浮点数,小端序 data_bytes = struct.pack('<f', data) elif isinstance(data, (bytes, bytearray)): data_bytes = data else: raise TypeError("当前仅支持int、float、bytes类型数据写入") # 逐字节写入EEPROM,和C宏逻辑一致 for offset in range(len(data_bytes)): eeprom.write(address + offset, data_bytes[offset]) # 部分固件的模拟EEPROM需要调用commit才会把缓存写入存储,不支持该方法的固件可以删掉这行 if hasattr(eeprom, 'commit'): eeprom.commit()
情况2:外接I2C接口EEPROM芯片
from machine import I2C, Pin import struct import time # 初始化I2C,scl、sda引脚根据你的硬件接线调整 i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000) # EEPROM的I2C设备地址,AT24C系列默认一般为0x50,可根据硬件ADDR引脚接线调整 EEPROM_DEV_ADDR = 0x50 def eeprom_write_i2c(address, data): # 把输入数据转为字节序列 if isinstance(data, int): data_bytes = data.to_bytes(4, byteorder='little', signed=True) elif isinstance(data, float): data_bytes = struct.pack('<f', data) elif isinstance(data, (bytes, bytearray)): data_bytes = data else: raise TypeError("当前仅支持int、float、bytes类型数据写入") # 逐字节写入,兼容性最好,不需要处理页写入的跨页问题 for offset in range(len(data_bytes)): write_addr = address + offset # 构造写入帧:2字节EEPROM地址 + 1字节数据(适配容量大于256字节的EEPROM) buf = bytearray([(write_addr >> 8) & 0xFF, write_addr & 0xFF, data_bytes[offset]]) i2c.writeto(EEPROM_DEV_ADDR, buf) # 等待EEPROM写入完成,固定5ms兼容所有AT24C系列芯片 time.sleep_ms(5)
注意事项
- 如果需要写入结构体等价的数据,可以用
struct.pack一次性把多个字段打包为字节序列,再传入写入函数即可 - 字节序、数据长度要和你原来的C代码运行环境保持一致,不然会出现读写数据不匹配的问题
内容的提问来源于stack exchange,提问作者user14603676
相关产品推荐
相关产品推荐

