文章目录
- 问题描述
- 解决方法
- 总结
2023/11/29
问题描述
使用AT24C02模块,写入数据后立刻读取,读取到的数据出现异常,异常值为0xFF。
例如我们在主函数里,首先调用AT_Write
函数往模块的0地址写入一个数据,接着多次调用AT_Read
函数从0地址处读取写入的数据,读取到的数据部分会发生错误,具体表现为前几次读取到的数据为0xFF,后几次读取到的数据恢复正常。
解决方法
在 Rev. 0976F–SEEPR–10/02 版数据手册的第九页,我们可以看到如下描述:
大体为:当我们往AT模块成功写入8位数据时,AT模块会回复我们一个0(即IIC通信的应答位),之后AT会进入一个短暂的内部定时写周期 twr,在该阶段AT需要把我们发送的8位数据存储到对应的地址,所以在该阶段内所有AT模块的写入操作都会被禁止,模块不再响应外部的请求。
也就是说,当我们在调用了AT_Write
函数往模块里写入一个数据时,数据需要一定的时间才能写到模块的flash中,在这个时间段内,模块需要专心处理往flash中写数据的操作,不再响应外部的请求,此时我们调用AT_Read
函数返回的当然是一个错误的数据。只有在等待一定的时间,写flash操作完成后,模块才会再次响应我们的请求,此时,我们再调用AT_Read
函数返回的数据就变成了正常的数值。这也就解释了为什么当我们连续多次调用AT_Read
函数时前几次返回的是错误的数据,后几次返回的是正确的数据。
我们使用逻辑分析仪进行验证:首先,我们往AT模块的0x02地址写入数值0x06,之后立刻从0x02地址读取数据,此时读取到的数据就变成了0xFF,而不是我们希望的0x06。
其实仔细观察可以发现,在返回0xFF数据前,AT回应给我们的是一个NACK。但部分同学使用的函数中并未对IIC返回NACK有特定的处理,而是在返回NACK后仍然从SDA总线上强行读取数据,我们知道,当IIC总线空闲时,总线电平会由上拉电阻上拉至高电平,此时从SDA读取到的数据也就变成了0xFF。
至此我们就可以针对以上的问题找到相应的解决方法了:1. 首先,我们往AT模块写入数据后,不能立刻读取数据,需要等待几个毫秒后再次读取,躲开模块的内部定时写周期 twr。 2. 要规范自己的函数,在检测到IIC回复NACK后,需要进行特定的处理,例如数据重发、检查芯片状态等,而不是强行从IIC总线读取数据。
总结
- 存储模块会有内部定时写周期 twr,需要注意。
- 规范自己的函数,将情况考虑周全,在出现不同的情况时会有不同的返回值。(例如让
AT_Read
函数返回一个16位数据,低八位存储从AT模块中读取的数据,最高位存储AT模块读取情况,在检测到NACK后将最高位置一,此时就可以通过检测AT_Read
函数返回的16位数据最高位状态来判断AT模块的读取情况)