billjiang2008 发表于 2018-2-10 11:21:39

STM32 HAL库 关于IIC硬件多字读写的疑问

本帖最后由 billjiang2008 于 2018-2-10 11:23 编辑

最近在做IIC读写程序,用到HAL库,发现利用HAL库 对IIC读写问题,求助一下!

在HA库对IIC读写操作的2个库函数如下:

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)



HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)


我利用库函数对EEPROM的多字节读写做了实验如下:

HAL_StatusTypeDef EEPROM_WriteData(uint16_t MemAddr,uint8_t *pData,uint16_t Size)
{
      uint16_t i;
      HAL_StatusTypeDef sta;
      
      for(i=0;i<Size;i++)
      {
                MemAddr += i;
                sta = HAL_I2C_Mem_Write(&hi2c1,0XA0,MemAddr,I2C_MEMADD_SIZE_8BIT,&pData,1,HAL_MAX_DELAY);//利用库函数一个一个字节的将 数据写到EEPROM中
                if(sta != HAL_OK)
                        return sta;
                HAL_Delay(1);
      }
}

HAL_StatusTypeDef EEPROM_ReadData(uint16_t MemAddr,uint8_t *pData,uint16_t Size)
{
      uint16_t i;
      HAL_StatusTypeDef sta;
      
      for(i=0;i<Size;i++)
      {
                MemAddr += i;
                sta = HAL_I2C_Mem_Read(&hi2c1,0XA0,MemAddr,I2C_MEMADD_SIZE_8BIT,&pData,1,HAL_MAX_DELAY);//利用库函数一个一个字节的将数据读到缓存中
                if(sta != HAL_OK)
                        return sta;
                HAL_Delay(1);
      }
}


开始测试连续读写数据:

      uint16_t i;
      uint8_t Dat_Write;
      uint8_t Datread ;//读缓存
/* Infinite loop */
      taskENTER_CRITICAL();
      
      printf("*************EEPROM数据测试******************** \r\n");
      printf("待写入数据:\n");
      for(i=0;i<256;i++)
      {
                Datread=0;
                Dat_Write=0X00;
                printf("0X%02X",Dat_Write);
                if(i%16==15)
                {
                        printf("\n");
                }
      }
      
      EEPROM_WriteData(0,Dat_Write,8);
      EEPROM_WriteData(8,&Dat_Write,8);
      EEPROM_WriteData(16,&Dat_Write,8);
      
                printf("\n");
      printf("读出的数据:\n");
               
      EEPROM_ReadData(0,&Datread,8);
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);               
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);      
      printf("0X%02X\r\n",Datread);      
      
      EEPROM_ReadData(8,&Datread,8);
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);               
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);
      
      EEPROM_ReadData(16,&Datread,8);
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);
      printf("0X%02X",Datread);               
       printf("0X%02X",Datread);
      printf("0X%02X",Datread);      
      printf("0X%02X",Datread);


以上程序,输出结果正常,数据读写正常!

于是想直接利用库函数,进行多字节读写,出现了问题,
这个库函数
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

于是把以上程序的      EEPROM_WriteData(0,Dat_Write,8);
                              EEPROM_WriteData(8,&Dat_Write,8);
                              EEPROM_WriteData(16,&Dat_Write,8);
改写为:
                   HAL_I2C_Mem_Write(&hi2c1,0XA0,0,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);//红色字体的8是表示连续读8个字节?
                   HAL_I2C_Mem_Write(&hi2c1,0XA0,8,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);
                   HAL_I2C_Mem_Write(&hi2c1,0XA0,16,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);


把读                   EEPROM_ReadData(0,&Datread,8);
                         EEPROM_ReadData(8,&Datread,8);
                         EEPROM_ReadData(16,&Datread,8);
改写为:
                        HAL_I2C_Mem_Read(&hi2c1,0XA0,0,I2C_MEMADD_SIZE_8BIT,&Datread,8,HAL_MAX_DELAY);//红色字体的8是表示连续读8个字节?
                        HAL_I2C_Mem_Read(&hi2c1,0XA0,8,I2C_MEMADD_SIZE_8BIT,&Datread,8,HAL_MAX_DELAY);
                        HAL_I2C_Mem_Read(&hi2c1,0XA0,16,I2C_MEMADD_SIZE_8BIT,&Datread,8,HAL_MAX_DELAY);

改后,看串口输出数据,发现数据不正确,望高手指点,哪里出了问题!多谢!

toofree 发表于 2018-2-11 01:59:01

本帖最后由 toofree 于 2018-2-11 02:07 编辑

HAL_Delay(1);
这一条延时很重要。
你在下面这三条之间必须加个延时。一般的EEPROM在发送完前一个停止位后,到下一个起始位开始之前,需要保证最大5ms的延时,最小多少得自己实际测试摸底。不知道你用的EEPROM需要多少延时。HAL_I2C_Mem_Write(&hi2c1,0XA0,0,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);//红色字体的8是表示连续读8个字节?
                   HAL_I2C_Mem_Write(&hi2c1,0XA0,8,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);
                   HAL_I2C_Mem_Write(&hi2c1,0XA0,16,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);



nyszx 发表于 2018-2-11 09:53:06

toofree 发表于 2018-2-11 01:59
HAL_Delay(1);
这一条延时很重要。
你在下面这三条之间必须加个延时。一般的EEPROM在发送完前一个停止位后 ...

这个厉害呀:半夜还没休息,还在帮助坛友。

toofree 发表于 2018-2-11 09:59:50

nyszx 发表于 2018-2-11 09:53
这个厉害呀:半夜还没休息,还在帮助坛友。

要睡之前扫了一眼坛子,正好遇到了,就又坚持了一会儿

billjiang2008 发表于 2018-2-11 11:38:37

toofree 发表于 2018-2-11 01:59
HAL_Delay(1);
这一条延时很重要。
你在下面这三条之间必须加个延时。一般的EEPROM在发送完前一个停止位后 ...

加了延时还是数据不正确!
HAL_I2C_Mem_Write(&hi2c1,0XA0,0,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_MAX_DELAY);//红色字体的8是表示连续读8个字节

我想知道参数中的8 是连续写8个字节数据吗?

toofree 发表于 2018-2-11 12:33:31

billjiang2008 发表于 2018-2-11 11:38
加了延时还是数据不正确!
HAL_I2C_Mem_Write(&hi2c1,0XA0,0,I2C_MEMADD_SIZE_8BIT,&Dat_Write,8,HAL_ ...

是的,一般来说是连续写8个,不带停止位的。也就是说这个写不能跨页

Tcreat 发表于 2018-2-11 13:17:46

像6楼提及的 EPROM的连续写操作是不支持跨page的 一般EPROM的一个page 是128字节以开始写地址算 如果某个地址超过了开始写地址的当前page的话EPROM会自动回到盖page的开始处写 并不是按给的地址 到下个page所以如果一个写操作跨了多个page的话简易根据EPROM的page地址 每个page这行一次连续写操作

zhangjie2911 发表于 2019-1-8 11:19:09

EEPROM读取的地址不应该是0xa1吗?为什么我看你发送和读取的地址都是0xa0,并且还能读取成功?

羽夜霜降 发表于 2019-1-16 21:54:39

楼主你好,我现在用cubemx生成的hal_i2c_mem_read函数,发设备地址0x6b,寄存器地址0x01。用示波器发现,发设备地址的时候函数把最低位置0了,也就是改为了写的逻辑电平,我把他改回来发出0x6b的波形后,无法产生0x01的波形,请问你产生的波形是什么样子,谢谢!我的邮箱是768839134@qq.com,方便的话是否可以分享一下你成功的代码
页: [1]
查看完整版本: STM32 HAL库 关于IIC硬件多字读写的疑问