完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
读写EEPROM
EPPROM使用的是ST的M24C64芯片,MCU使用的是NXP的RT1051芯片,所以以下代码用的是NXP提供的fsl库和STM32的库略有不同。 IIC初始化 使用单片机硬件IIC接口,只需要配置时钟,引脚,设置波特率,其他获取默认设置就可以使用了。若芯片没有接到单片机的IIC接口用GPIO模拟IIC时序也可以实现功能,但是需要在对应时序加临界区保护。 IIC时序 使用硬件IIC可以跳过本部分内容。 开始结束时序 IIC开始时序和结束时序如图1所示: 图1 IIC开始和结束符 开始时序: SCL高电平时,拉低SDA 结束时序:先拉高SCL,然后拉高SDA ### 数据发送 图2 数据传输 因为这是个从站芯片,所以DATA IN和OUT相对于单片机来说是反的,即单片机输出是从站芯片的输入。SCL拉高后,根据数据拉高或者拉低SDA电平。bit9是等待从站发送的ACK 芯片地址 图3 芯片地址 24系列高4位是产商固定的1010,A2-A0这三位取决于硬件,若都是接地就是000,若A0接上拉电阻,其他接地则是001。最后一位1代表读,0代表写. 使用硬件IIC的需要注意,在配置结构体中地址可能需要右移一位,读写会在结构体另外参数配置,库函数中会拼接成一个字节的。需要关注一下库函数怎么实现的,这个坑我也踩了一会。 读写EEPROM 这个只需要参考数据手册的时序图发送或者接受数据就ok了,野火的教程中比较详细。正点原子的比较简单好懂。但是一定要看数据收册!一定要看数据收册!数据收册! 图4 写数据时序图 踩的坑 踩的坑 一个非常简单的读写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个字节。 图5 24C64时序图 图6 24C02时序图 24C02的word address只有一个字节。啰嗦一句**一定要看数据收册!一定要看数据收册!数据收册!** 以上内容参考正点原子野火历程,将自己踩的坑整理出来。只是用来分享所学知识无商业用途。若理解错误还希望大佬指出,欢迎大家留言交流。 |
|
|
|
只有小组成员才能发言,加入小组>>
3320 浏览 9 评论
2998 浏览 16 评论
3496 浏览 1 评论
9066 浏览 16 评论
4089 浏览 18 评论
1186浏览 3评论
612浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
602浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2339浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1899浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 05:45 , Processed in 1.004558 second(s), Total 49, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号