读写EEPROM
EPPROM使用的是ST的M24C64芯片,MCU使用的是NXP的RT1051芯片,所以以下代码用的是NXP提供的fsl库和STM32的库略有不同。
IIC初始化
使用单片机硬件IIC接口,只需要配置时钟,引脚,设置波特率,其他获取默认设置就可以使用了。若芯片没有接到单片机的IIC接口用GPIO模拟IIC时序也可以实现功能,但是需要在对应时序加临界区保护。
IIC时序
使用硬件IIC可以跳过本部分内容。
开始结束时序
IIC开始时序和结束时序如图1所示:
芯片地址
使用硬件IIC的需要注意,在配置结构体中地址可能需要右移一位,读写会在结构体另外参数配置,库函数中会拼接成一个字节的。需要关注一下库函数怎么实现的,这个坑我也踩了一会。
读写EEPROM
这个只需要参考数据手册的时序图发送或者接受数据就ok了,野火的教程中比较详细。正点原子的比较简单好懂。但是一定要看数据收册!一定要看数据收册!数据收册!
踩的坑
一个非常简单的读写EEPROM的实验,因为硬件正好是IIC引脚所以准备直接用,不用模拟的IIC,在正点原子和野火几乎每个开发板都有IIC的实验,所以我直接用了里面的代码,但是发现读回来都是0xFF,然后百度了一下有个老哥说需要配置引脚为开漏输出,不然M24C64的引脚拉不下去。我照着修改了配置,发现并不行。
u8 AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
u8 status=0;
u8 writedata=0;
writedata=DataToWrite;
//配置I2C xfer结构体
at24cxx_xfer.slaveAddress=AT24C02_ADDR; //设备地址
at24cxx_xfer.direction=kLPI2C_Write; //写入数据
at24cxx_xfer.subaddress=(u32)WriteAddr; //要读取的寄存器地址
at24cxx_xfer.subaddressSize=1; //地址长度一个字节
at24cxx_xfer.data=&writedata; //要写入的数据
at24cxx_xfer.dataSize=1; //写入数据长度1个字节
at24cxx_xfer.flags=kLPI2C_TransferDefaultFlag;
if(LPI2C_MasterTransferBlocking(LPI2C1,&at24cxx_xfer)==kStatus_Fail)
status=1;
delay_ms(10); //AT24C02写周期最大5ms,所以这里要有延时
return status;
}
然后看了下官方fsl库函数里面的定义的也就这几个东西,并不是因为缺少配置才导致读取失败。
struct _lpi2c_master_transfer
{
uint32_t
flags; /*!< Bit mask of options for the transfer. See enumeration #_lpi2c_master_transfer_flags for available
options. Set to 0 or #kLPI2C_TransferDefaultFlag for normal transfers. */
uint16_t slaveAddress; /*!< The 7-bit slave address. */
lpi2c_direction_t direction; /*!< Either #kLPI2C_Read or #kLPI2C_Write. */
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
size_t subaddressSize; /*!< Length of sub address to send in bytes. Maximum size is 4 bytes. */
void *data; /*!< Pointer to data to transfer. */
size_t dataSize; /*!< Number of bytes to transfer. */
};
度娘上也有好多人说把开发板上的EEPROM卸了换M24C64不能读写,讲道理ST也是个大厂,不会做的这么难用才对。后来看了datesheet才恍然大悟。因为24C64有8KB的存储空间,而24C02只有256B的空间所以地址大小不一致,所以24C64的地址占了2个字节。