STM32:I2C-EEPROM

STM32:I2C-EEPROM

前提摘要

  1. 个人说明:

  2. 参考:

    • 正点原子
    • 野火
    • ST数据手册

正文

EEPROM读写需要注意

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

    在这里插入图片描述

  2. 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[i]);
    }

此时EEPROM理想存储情况

地址0x040x050x060x070x08
写入数据0xfe0xfd0xfc0xfb0xfa
实际读出数据0xfe0xfd0xfc0xfb8

在这里插入图片描述

这是由于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); 
            }
        }
    } 
}

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

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

总结


本文均为原创,欢迎转载,请注明文章出处:CSDN:https://blog.csdn.net/ZipingPan/ARM。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

非原创博客会在文末标注出处,由于时效原因,可能并不是原创作者地址(已经无法溯源)。

  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pan2iping

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值