打印
[应用相关]

STM32:I2C-EEPROM

[复制链接]
376|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-4-30 16:25 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
正文
EEPROM读写需要注意

EEPROM读写操作之间,距离下一次操作需要留一定时间,给EEPROM芯片处理数据的时间,不能立即去读写的数据。



EEPROM多字节读写,需要注意页对齐的问题,不然会出现数据没有成功写入。

情况一:单字节连续读写
具体I2C配置和应用层程序请参考前文

主函数,main.c

    uint8_t wr_data = 0xfe;
    uint8_t rd_data = 0;

    BSP_UART_Init();
    BSP_I2C_Init();
    BSP_I2C_WR_Byte(wr_data,EEPROM_ADDRESS7,0x00);
    BSP_I2C_ReadBuffer(&rd_data,EEPROM_ADDRESS7,0x00,1);
    printf("%x",rd_data);




会发现此时会报错I2C读,EV6和EV8事件,查询STM32F1参考手册,会发现从设备对ADDR无应答。

改进:此时加入等待从设备程序
主函数,main.c

    uint8_t wr_data = 0xfe;
    uint8_t rd_data = 0;

    BSP_UART_Init();
    BSP_NVIC_Config();
    BSP_I2C_Init();
    BSP_I2C_WR_Byte(wr_data,EEPROM_ADDRESS7,0x00);
    BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
    BSP_I2C_ReadBuffer(&rd_data,EEPROM_ADDRESS7,0x00,1);
    printf("%x",rd_data);




即可正常读出程序。

情况二:多字节地址对齐
具体I2C配置和应用层程序请参考前文

主函数,main.c

    uint8_t wr_data[5] = {0xfe,0xfd,0xfc,0xfb,0xfa};
    uint8_t rd_data[5] = {0};

    BSP_UART_Init();
    BSP_NVIC_Config();
    BSP_I2C_Init();
    BSP_I2C_WriteBuffer(wr_data,EEPROM_ADDRESS7,0x04,sizeof(wr_data)/sizeof(uint8_t));
    BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
    BSP_I2C_ReadBuffer(rd_data,EEPROM_ADDRESS7,0x04,sizeof(rd_data)/sizeof(uint8_t));
    for(int i = 0;i<5;i++)
    {
        printf("rd_data[%d] = %x\r\n",i,rd_data);
    }


此时EEPROM理想存储情况





这是由于EEPROM多字节写入必须要考虑页对齐的情况,同时一次写入不能超过EEPROM页大小。

1Kbit/2Kbit大小的EEPROM最多写入8Byte;
4Kbit/8Kbit/16Kbit大小的EEPROM最多写入16Byte;
void BSP_I2C_EE_Page_BufferWrite(uint8_t *pBuffer,uint8_t WriteAddr,uint8_t NumBytetoWrite)
{
    if(NumBytetoWrite > EE_PAGE_SIZE)
        NumBytetoWrite = EE_PAGE_SIZE;
    BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,NumBytetoWrite);
}


不定长字节写入,没有页写入的最大字节8Byte限制

void BSP_I2C_EE_BufferWrite(uint8_t *pBuffer,uint8_t WriteAddr,uint8_t NumBytetoWrite)
{
    uint8_t NumofPage = 0,NumofSingle = 0,Addr = 0,Addr_Cnt = 0,Addr_Temp = 0;

    Addr = WriteAddr % EE_PAGE_SIZE;
    Addr_Cnt = EE_PAGE_SIZE - Addr;
    NumofPage = NumBytetoWrite  / EE_PAGE_SIZE;
    NumofSingle = NumBytetoWrite % EE_PAGE_SIZE;

    if(Addr == 0){
        if(NumofPage == 0){
            BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,NumBytetoWrite);
            BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
        }
        else{
            while(NumofPage--){
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,EE_PAGE_SIZE);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
                WriteAddr += EE_PAGE_SIZE;
                pBuffer += EE_PAGE_SIZE;
            }
            if(NumofSingle != 0){
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,NumofSingle);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
            }
        }   
    }
    else{
        if(NumofPage == 0){
            if(NumofSingle > Addr_Cnt){
                Addr_Temp = NumofSingle - Addr_Cnt;
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,Addr_Cnt);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
                WriteAddr += Addr_Cnt;
                pBuffer += Addr_Cnt;

                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,Addr_Temp);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
            }
            else{
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,NumBytetoWrite);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
            }
        }
        else{
            NumBytetoWrite -= Addr_Cnt;
            NumofPage = NumBytetoWrite  / EE_PAGE_SIZE;
            NumofSingle = NumBytetoWrite % EE_PAGE_SIZE;
            if(Addr_Cnt != 0){
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,Addr_Cnt);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
                WriteAddr += Addr_Cnt;;
                pBuffer += Addr_Cnt;
            }
            while(NumofPage--){
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,EE_PAGE_SIZE);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
                WriteAddr += EE_PAGE_SIZE;
                pBuffer += EE_PAGE_SIZE;

            }
            if(NumofSingle != 0){
                BSP_I2C_KeepWrite(pBuffer,EEPROM_ADDRESS7,WriteAddr,NumofSingle);
                BSP_I2C_WaitStandByState(EEPROM_ADDRESS7);
            }
        }
    }
}



上述代码主要分为以下几种情况。

写入的数据的首地址页对齐。
数据长度没有超过一页的大小(8Byte),则直接写入。
数据长度超过一页的大小(8Byte),先按页写入,再将多余的写入新的一页。
写入的数据的首地址并不是页对齐。
数据长度没有超过一页的大小(8Byte)
数据首地址距离页尾的空间不足以放下整个数据,则先补全该页,再将剩余的数据写到下一页。
数据首地址距离页尾的空间足以放下整个数据,则直接写入。
数据长度超过一页的大小(8Byte)
先补全该页,再按页写入,再将剩余的数据写到下一页。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/ZipingPan/article/details/137314177

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1931

主题

15650

帖子

12

粉丝