野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 7527|回复: 1

STM32库开发实战指南关于用I2C操作24C02的bug

[复制链接]
发表于 2018-5-28 15:57:10 | 显示全部楼层 |阅读模式
函数I2C_EE_BufferWrite中,对于需要写入的起始地址与整数页数是否对齐进行了判断,并且对写入的数据总数是否满足整数页数进行了判断。在处理写入地址非对齐模式的时候有bug。见如下代码:void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

  Addr = WriteAddr % I2C_PageSize;
  count = I2C_PageSize - Addr;
  NumOfPage =  NumByteToWrite / I2C_PageSize;
  NumOfSingle = NumByteToWrite % I2C_PageSize;

  /* If WriteAddr is I2C_PageSize aligned  */
  if(Addr == 0)
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0)
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else  
    {
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
                                I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize;
      }

      if(NumOfSingle!=0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }
  /* If WriteAddr is not I2C_PageSize aligned  */
  else
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0) //这里没有考虑到写入的地址不是跟I2C_PageSize对齐,并且写入的数量超过一页的情况。
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / I2C_PageSize;
      NumOfSingle = NumByteToWrite % I2C_PageSize;       

      if(count != 0)
      {  
        I2C_EE_PageWrite(pBuffer, WriteAddr, count);
        I2C_EE_WaitEepromStandbyState();
        WriteAddr += count;
        pBuffer += count;
      }

      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
        I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize;  
      }
      if(NumOfSingle != 0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }  
}


上述代码中没有考虑到不对齐的时候,如果写入的数据超过当前页剩余的部分,就会出现这小部分覆盖了前面的数据的情况。比如从0x03开始写入7个字节,当前分页剩余只有5个字节,写入7个会依次写入到0x03,0x04,0x05,0x06,0x07,0x00,0x01覆盖0x00,0x01这两个字节。此处应该对当前页剩余的字节数进行一个判断。
回复

使用道具 举报

发表于 2018-5-28 16:03:20 | 显示全部楼层
是的,这个程序没有考虑那种情况,现在改成这个版本,已经更新到RT1052产品的代码和说明文档里了:
  1. /**
  2.   * @brief 向EEPROM写入不限量的数据,超出EEPROM_SIZE后覆盖旧数据
  3.   * @note  调用本函数后必须调用I2C_EEPROM_WaitStandbyState进行等待
  4.   * @param ClientAddr:EEPROM的I2C设备地址(8位地址)
  5.   * @param WriteAddr:写入的存储单元首地址
  6.   * @param pBuffer:缓冲区指针
  7.   * @param NumByteToWrite:要写的字节数,不可超过EEPROM_PAGE_SIZE定义的值
  8.   * @retval  无
  9.   */
  10. void I2C_EEPROM_Buffer_Write( uint8_t ClientAddr,
  11.                               uint8_t WriteAddr,
  12.                               uint8_t* pBuffer,  
  13.                               uint16_t NumByteToWrite)
  14. {
  15.   uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
  16.   /* 后续要处理的字节数,初始值为NumByteToWrite*/
  17.   uint8_t NumByteToWriteRest = NumByteToWrite;
  18.   /* 根据以下情况进行处理:
  19.     1.写入的首地址是否对齐
  20.     2.最后一次写入是否刚好写满一页 */
  21.   Addr = WriteAddr % EEPROM_PAGE_SIZE;
  22.   count = EEPROM_PAGE_SIZE - Addr;
  23.   
  24.   /* 若NumByteToWrite > count:
  25.      第一页写入count个字节,对其余字节再进行后续处理,
  26.      所以用 (NumByteToWriteRest = NumByteToWrite - count) 求出后续的NumOfPage和NumOfSingle进行处理。
  27.      若NumByteToWrite < count:
  28.      即不足一页数据,直接用NumByteToWriteRest = NumByteToWrite求出NumOfPage和NumOfSingle即可 */
  29.   NumByteToWriteRest = (NumByteToWrite > count) ? (NumByteToWrite - count) : NumByteToWrite;
  30.   
  31.   /* 要完整写入的页数(不包括前count字节)*/
  32.   NumOfPage =  NumByteToWriteRest / EEPROM_PAGE_SIZE;
  33.   /* 最后一页要写入的字节数(不包括前count字节)*/
  34.   NumOfSingle = NumByteToWriteRest % EEPROM_PAGE_SIZE;

  35.   /* NumByteToWrite > count时,需要先往第一页写入count个字节
  36.      NumByteToWrite < count时无需进行此操作 */
  37.   if(count != 0 && NumByteToWrite > count)
  38.   {  
  39.     I2C_EEPROM_Page_Write(ClientAddr, WriteAddr, pBuffer, count);
  40.     I2C_EEPROM_WaitStandbyState(ClientAddr);
  41.     WriteAddr += count;
  42.     pBuffer += count;
  43.   }   
  44.   
  45.   /* 处理后续数据 */
  46.   if(NumOfPage== 0 )
  47.   {
  48.     I2C_EEPROM_Page_Write(ClientAddr, WriteAddr, pBuffer, NumOfSingle);
  49.     I2C_EEPROM_WaitStandbyState(ClientAddr);
  50.   }
  51.   else
  52.   {   
  53.     /* 后续数据大于一页 */
  54.     while(NumOfPage--)
  55.     {
  56.       I2C_EEPROM_Page_Write(ClientAddr, WriteAddr, pBuffer, EEPROM_PAGE_SIZE);
  57.       I2C_EEPROM_WaitStandbyState(ClientAddr);
  58.       WriteAddr +=  EEPROM_PAGE_SIZE;
  59.       pBuffer += EEPROM_PAGE_SIZE;  
  60.     }
  61.     /* 最后一页 */
  62.     if(NumOfSingle != 0)
  63.     {
  64.       I2C_EEPROM_Page_Write(ClientAddr, WriteAddr, pBuffer, NumOfSingle);
  65.       I2C_EEPROM_WaitStandbyState(ClientAddr);
  66.     }
  67.   }  
  68. }
复制代码


回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-7 17:29 , Processed in 0.052702 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表