你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于STM32F4 HAL库操作外部EEPROM的疑惑

[复制链接]
kgq398 提问时间:2014-11-3 10:58 /
关于STM32F4 HAL库操作外部EEPROM的疑惑

最近在搞24C16存储器,用的是STM32F429,工程使用CUBEMX工具生成的,因此使用的是HAL库,
但是发现HAL库提供存储器的函数就两个HAL_I2C_Mem_Write和HAL_I2C_Mem_Read,HAL库已经没有了原来DSP库的那么多函数了
我的代码如下,
static void I2Cx_Init(void)
{
  if(HAL_I2C_GetState(&heval_I2c) == HAL_I2C_STATE_RESET)
  {
    heval_I2c.Instance = I2C2;                        //I2C1
    heval_I2c.Init.ClockSpeed      = I2C_SPEED;
    heval_I2c.Init.DutyCycle       = I2C_DUTYCYCLE_2;
    heval_I2c.Init.OwnAddress1     = 0;
    heval_I2c.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;
    heval_I2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
    heval_I2c.Init.OwnAddress2     = 0;
    heval_I2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
    heval_I2c.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLED;  

    /* Init the I2C */
    I2Cx_MspInit();
    HAL_I2C_Init(&heval_I2c);   
  }
}

void Delayiic()
{
        unsigned int i;
        for(i=0;i<500000;i++);
}



void EEPROM_WriteByte(uint16_t addr,uint8_t dat)
{
   HAL_I2C_Mem_Write(&heval_I2c,0xA0,addr,I2C_MEMADD_SIZE_8BIT,&dat,1,1000);
         Delayiic();       
}
uint8_t EEPROM_ReadByte(uint16_t addr)
{
        uint8_t dat;
   HAL_I2C_Mem_Read(&heval_I2c, 0xA0, addr, I2C_MEMADD_SIZE_8BIT, &dat, 1,1000);
         Delayiic();       
        return dat;
}

void TestIIC(void)
{
           unsigned int i=0;

          tmp12= HAL_I2C_IsDeviceReady(&heval_I2c,0xA0,3000,1000);  //检查器件准备好
    for(i=0;i<100;i++)
                  EEPROM_WriteByte(i,0x77);
                for(i=0;i<100;i++)
                  {
                                IIC_DAT[i]=EEPROM_ReadByte(i);
                                if(IIC_DAT[i]!=0x77)
                                        err++;
                        }
                        while(1);       
}

经过测试,读写极不稳定,有时候对,有时候不对。
坛子里有用HAL库IIC的吗,或者版主来一下,帮忙解决一下
收藏 评论22 发布时间:2014-11-3 10:58

举报

22个回答
yyblike-263448 回答时间:2015-5-14 08:56:37
本帖最后由 yyblike-263448 于 2015-5-14 08:58 编辑

看了大家在写的时候是一个字节一个字节的写,按照EEPROM的写要求,写数据需要5ms的延时,那么我写200个字节的硬件延时就1s了,我的方法是这样的,能正常写数据。初始化和读直接调用的库。每次跨页的时候才有一个5ms的写周期延时。

  1. void I2C2_WriteBuff16(uint8_t deviceAddr,uint16_t writeAddr,uint8_t *pData,uint8_t size)
  2. {
  3.         uint8_t temp;
  4.         if (HAL_I2C_Mem_Write(&hi2c2,deviceAddr,writeAddr,I2C_MEMADD_SIZE_16BIT,pData,size,I2C_TIMEOUT)!= HAL_OK)
  5.         {}
  6.         while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY);
  7. }
复制代码

  1. /* EEPROM写数据 */
  2. void EE_WriteBuff(uint8_t deviceAddr,uint16_t writeAddr,uint8_t *pData,uint8_t size)
  3. {
  4.         uint8_t index;
  5.         uint8_t temp1,temp2,temp3;
  6.         uint16_t addrTemp = writeAddr;

  7.         temp1 = EE_PAGE_SIZE - writeAddr % EE_PAGE_SIZE;
  8.         if(size > temp1)                                //写数据超过当前页能写数据
  9.         {
  10.                 temp2 = (size-temp1) / EE_PAGE_SIZE;        //整页数
  11.                 temp3 = (size-temp1) % EE_PAGE_SIZE;        //最后页写字节数
  12.         }
  13.         else                                                                                //写数据不跨页
  14.         {
  15.                 temp1 = size;                                        //单页
  16.                 temp2 = 0;
  17.                 temp3 = 0;
  18.         }
  19.         if(temp1)                                                                //写开始页
  20.         {
  21.                 I2C2_WriteBuff16(deviceAddr,addrTemp,pData,temp1);
  22.                 pData = pData+temp1;        //数据指针偏移
  23.                 addrTemp += temp1;
  24.                 DelayMs(8);                                        //必须,5ms写周期,否则写出错
  25.         }
  26.         if(temp2)                                                                //写整数页
  27.         {
  28.                 for(index = 0;index<temp2;index++)
  29.                 {
  30.                         I2C2_WriteBuff16(deviceAddr,addrTemp,pData,EE_PAGE_SIZE);
  31.                         pData = pData+EE_PAGE_SIZE;
  32.                         addrTemp += EE_PAGE_SIZE;
  33.                         DelayMs(8);
  34.                 }
  35.         }
  36.         if(temp3)                                                                //写最后剩余数据
  37.         {
  38.                 I2C2_WriteBuff16(deviceAddr,addrTemp,pData,temp3);
  39.                 DelayMs(8);
  40.         }
  41. }
复制代码



冬子 回答时间:2014-11-3 15:13:02
我写正常,就是读多字节的时候不太正常
kgq398 回答时间:2014-11-3 15:14:26
楼上的能否分享一下你的代码,我只需要一个一个读出来就可以,
冬子 回答时间:2014-11-3 16:56:53
写的时候只能一个个字节写,每写完一个延时一下,请懂的指正
        for(i=0;i<10;i++)
        {
                USART6_RXD_Buffer[i]=0x01+i;
                HAL_I2C_Mem_Write(&hi2c1,0xa0,100+i,I2C_MEMADD_SIZE_8BIT,&USART6_RXD_Buffer[i],1,100);
                HAL_Delay(4);
        }

  我也正在调试
kgq398 回答时间:2014-11-3 18:19:38
是的,我发现,延时很重要,不延时的时候一次都不对
,高手进来解释一下
kgq398 回答时间:2014-11-4 09:05:09
再次顶起,看是否有人弄好的,难道HAL库没解决以前IIC硬件上总线占用的问题吗
冬子 回答时间:2014-11-4 13:51:12
解决了
HAL_StatusTypeDef EEPROM_WriteData(uint16_t MemAddress, uint8_t *pData, uint16_t Size)
{
        uint16_t i;
        HAL_StatusTypeDef sta;
        for(i=0;i<Size;i++)
        {
                MemAddress+=i;
                sta=HAL_I2C_Mem_Write(&hi2c1, 0xa0, MemAddress,I2C_MEMADD_SIZE_8BIT, &pData[i], 1, 200);
                if(sta!=HAL_OK)return sta;
                Delay(5000);
        }
        return sta;
}

HAL_StatusTypeDef EEPROM_ReadData(uint16_t MemAddress, uint8_t *pData, uint16_t Size)
{
        uint16_t i;
        HAL_StatusTypeDef sta;
        for(i=0;i<Size;i++)
        {
                MemAddress+=i;
                sta=HAL_I2C_Mem_Read(&hi2c1, 0xa0, MemAddress,I2C_MEMADD_SIZE_8BIT, &pData[i], 1, 200);
                if(sta!=HAL_OK)return sta;
                Delay(4000);
        }
        return sta;
}

还是那样,读与写必须一个一个字节地来,不知道这个CubeMX神马意思,还是咱位理解有误。
另外延时很重要,自带的HAL_Delay的延时函数一定要慎用,用不好会死机,只能自编一个延时函数了,会用HAL_Delay告诉一声,因为我发现只要在主程序初始化的时候调用HAL_Delay会死机,应该是什么东西没准备好
lzp3758 回答时间:2014-12-4 11:20:30
要启动SysTick后才可以使用HAL_Delay,HAL_Delay带有一个全局变量去计时就在systick 里面
埃斯提爱慕 回答时间:2015-1-13 22:55:26
提示: 作者被禁止或删除 内容自动屏蔽
lkl0305 回答时间:2015-1-14 00:18:47
学习中!
mlxy123xy 回答时间:2015-1-14 00:21:19
24c系列最高读写速度400k,一般都达不到的。肯定要延时。
拼命三郎 回答时间:2015-1-14 08:06:57
muyou xueguo
lcdi 回答时间:2015-5-14 10:04:21
看样子HAL库设计的还是不方便啊
yyblike-263448 回答时间:2015-5-17 09:23:07
lcdi 发表于 2015-5-14 10:04
看样子HAL库设计的还是不方便啊

在这里和HAL库没有任何关系,HAL库为你实现了读写多个字符的操作,这个主要还是和EEPROM器件有关,在读的过程中,可以直接调用读方法读任意的字节,但是写的过程中EEPROM规定是一页一页的写的,比如你一页16字节,你从0地址开始写17个字节,第0个地址会被第17个字节替换,为了防止替换才需要换页操作了,在其他库的操作中也同样需要这样,只不过在写一个字节的操作可能换页判断会简单点。
12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版