关于stm32模拟IIC对AT24C256指定地址读,但是数据一直为0xFF
·
项目场景:
这几天在复习stm32通过软件IIC与AT24C256进行通信,实现简单的指定地址写和当前地址读的简单操作。
问题描述
- 打算从指定地址0xDF写入0xAA,然后在0xDF读取数据,期望的值是0xAA,但一直为0xFF
#include "stm32f10x.h" // Device header
#include "MyIIC.h"
#include "Delay.h"
#include "AT24CXX.h"
void AT24CXX_Init(void)
{
MyIIC_Init();
}
void AT24CXX_WriteByte(uint8_t data,uint16_t addr)
{
MyIIC_Start();
MyIIC_SendByte(0xA0);//寻址写
MyIIC_ReciveAck();
MyIIC_SendByte(addr>>8);
MyIIC_ReciveAck();
MyIIC_SendByte(addr & 0xFF);
MyIIC_ReciveAck();
MyIIC_SendByte(data);
MyIIC_ReciveAck();
MyIIC_Stop();
Delay_ms(5);
}
uint8_t AT24CXX_ReadByte(uint16_t addr)
{
uint8_t data;
MyIIC_Start();
MyIIC_SendByte(0xA0);//寻址写
MyIIC_ReciveAck();
MyIIC_SendByte(addr>>8);
MyIIC_ReciveAck();
MyIIC_SendByte(addr&0xFF);
MyIIC_Start();//重复起始条件
MyIIC_SendByte(0xA1);//寻址读
MyIIC_ReciveAck();
data = MyIIC_ReciveByte();
MyIIC_SendACK(1);
MyIIC_Stop();
return data;
}
- 主函数调用
AT24CXX_Init();
AT24CXX_WriteByte(0xAA,0xDf);
uint8_t data = AT24CXX_ReadByte(0xDF);
原因分析:
使用逻辑分析仪捕获发现缺少了重复的起始条件

分析应该是起始条件和前一个字节数据的ack混淆了,回望指定地址读的代码发现,在发送最后低8位地址时,忘记了主机等待ACK。导致IIC将重复的起始信号当作前一个字节数据的ACK了。
解决方案:
在低8位地址后增加等待ACK

问题解决。
此外发现在对AT24C256进行先写后读操作时,需要给予一定时间,可采用延时的方式或者ACK轮询,在此介绍一种ack轮询方式查询写入操作是否完成,避免使用延时阻塞主程序。
void AT24CXX_WaitWriteComplete(void)
{
uint8_t ack=1;
do{
MyIIC_Start();
MyIIC_SendByte(0xA0);
ack = MyIIC_ReciveAck();
MyIIC_Stop();
}while(ack);
}
更多推荐


所有评论(0)