项目场景:

这几天在复习stm32通过软件IIC与AT24C256进行通信,实现简单的指定地址写和当前地址读的简单操作。


问题描述

  1. 打算从指定地址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);
}

更多推荐