[APM32F0] APM32F072硬件IIC读取温湿度传感器

[复制链接]
1612|11
 楼主| Alden 发表于 2023-3-22 11:39 | 显示全部楼层 |阅读模式
本帖最后由 Alden 于 2023-3-22 11:39 编辑

#技术资源#
APM32F072的硬件IIC例程中只有双板通讯和EEPROM的例程.
但无法直接用来用来跟其他IIC设备通讯,因此参考极海Eval板的硬件IIC例程和网上资料,改写了一个读写温湿度传感器HTU21D的例程。首先是IIC的初始化部分,与EEPROM的相同
  1. #define HTU_I2C                          I2C2
  2. #define HTU_I2C_CLK                      RCM_APB1_PERIPH_I2C2

  3. #define HTU_I2C_SCL_PIN                  GPIO_PIN_10
  4. #define HTU_I2C_SCL_GPIO_PORT            GPIOB
  5. #define HTU_I2C_SCL_GPIO_CLK             RCM_AHB_PERIPH_GPIOB
  6. #define HTU_I2C_SCL_SOURCE               GPIO_PIN_SOURCE_10
  7. #define HTU_I2C_SCL_AF                   GPIO_AF_PIN1

  8. #define HTU_I2C_SDA_PIN                  GPIO_PIN_11
  9. #define HTU_I2C_SDA_GPIO_PORT            GPIOB
  10. #define HTU_I2C_SDA_GPIO_CLK             RCM_AHB_PERIPH_GPIOB
  11. #define HTU_I2C_SDA_SOURCE               GPIO_PIN_SOURCE_11
  12. #define HTU_I2C_SDA_AF                   GPIO_AF_PIN1

  13. void APM_I2C_Init(void)
  14. {
  15.     GPIO_Config_T gpioConfigStruct;
  16.     I2C_Config_T i2cConfigStruct;
  17.    
  18.     /* Enable I2C related Clock */
  19.     RCM_EnableAHBPeriphClock(HTU_I2C_SCL_GPIO_CLK | HTU_I2C_SDA_GPIO_CLK);
  20.     RCM_EnableAPB1PeriphClock(HTU_I2C_CLK);
  21.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);

  22.     /* Connect I2C to SCL */
  23.     GPIO_ConfigPinAF(HTU_I2C_SCL_GPIO_PORT, HTU_I2C_SCL_SOURCE, HTU_I2C_SCL_AF);
  24.     /* Connect I2C to SDA */
  25.     GPIO_ConfigPinAF(HTU_I2C_SDA_GPIO_PORT, HTU_I2C_SDA_SOURCE, HTU_I2C_SDA_AF);
  26.     /* Config I2C GPIO */
  27.     gpioConfigStruct.mode = GPIO_MODE_AF;
  28.     gpioConfigStruct.speed = GPIO_SPEED_50MHz;
  29.     gpioConfigStruct.outtype = GPIO_OUT_TYPE_OD;
  30.     gpioConfigStruct.pupd = GPIO_PUPD_NO;
  31.     gpioConfigStruct.pin = HTU_I2C_SCL_PIN;
  32.     GPIO_Config(HTU_I2C_SCL_GPIO_PORT, &gpioConfigStruct);

  33.     gpioConfigStruct.pin = HTU_I2C_SDA_PIN;
  34.     GPIO_Config(HTU_I2C_SDA_GPIO_PORT, &gpioConfigStruct);

  35.     /*  Config I2C2 */
  36.     I2C_Reset(HTU_I2C);

  37.     i2cConfigStruct.ack = I2C_ACK_ENABLE;
  38.     i2cConfigStruct.ackaddress = I2C_ACK_ADDRESS_7BIT;
  39.     i2cConfigStruct.address1 = 0x00;
  40.     i2cConfigStruct.analogfilter = I2C_ANALOG_FILTER_ENABLE;
  41.     i2cConfigStruct.digitalfilter = I2C_DIGITAL_FILTER_0;
  42.     i2cConfigStruct.mode = I2C_MODE_I2C;
  43.     i2cConfigStruct.timing = 0xB0420F13;
  44.     I2C_Config(HTU_I2C,&i2cConfigStruct);

  45.     /* Enable I2Cx */
  46.     I2C_Enable(HTU_I2C);
  47.    
  48.     I2CInfo.address = HTU_ADDR_WR;
  49.    
  50.                 I2CInfo.addrNum = 1;
  51.                
  52. }
由HTU21D的手册可以看到设备地址和温湿度数据对应的寄存器地址。
652ac498275b6a8173a26cad7d4bd42.png
进行宏定义
  1. #define HTU_ADDR                0x80
  2. #define HTU_ADDR_WR (HTU_ADDR & 0xFE)
  3. #define HTU_ADDR_RD (HTU_ADDR | 0x01)

  4. //非主机模式
  5. #define HTU_TEMP    0xE3
  6. #define HTU_HUMI    0XE5
然后编写对应的读写函数,根据HTU21D的手册,读数据需要有一个等待转换的时间,最大需要50ms,这个等待需要加入读函数中。
  1. I2C_ERROR_T I2C_HTU_Read(uint8_t* buffer, uint16_t writeAddr, uint8_t number)
  2. {
  3.     I2C_ERROR_T errSta = I2C_OK;
  4.     uint32_t temp = number;
  5.      uint8_t read_Num;


  6.        
  7.     I2C_HandlingTransfer(HTU_I2C, I2CInfo.address, I2CInfo.addrNum, I2C_RELOAD_MODE_SOFTEND, I2C_GENERATE_START_WRITE);
  8.    
  9.     I2CInfo.timeout = I2C_LONG_TIMEOUT;
  10.     while(I2C_ReadStatusFlag(HTU_I2C, I2C_FLAG_TXINT) == RESET)
  11.     {
  12.         if((I2CInfo.timeout--) == 0)
  13.         {
  14.             errSta = I2C_TIMEOUT;
  15.             return I2C_Callback(10);
  16.         }
  17.     }


  18.     I2C_TxData(HTU_I2C, (uint8_t)(writeAddr & 0x00FF));
  19.    
  20.     I2CInfo.timeout = I2C_LONG_TIMEOUT;
  21.     while(I2C_ReadStatusFlag(HTU_I2C, I2C_FLAG_TXCF) == RESET)
  22.     {
  23.         if((I2CInfo.timeout--) == 0)
  24.         {
  25.             errSta = I2C_TIMEOUT;
  26.             return I2C_Callback(13);
  27.         }
  28.     }
  29.         APM_EVAL_DelayMs(50);//等待转化完成
  30.     /* I2Cx send the number of byte to write to eeprom */
  31.     I2C_HandlingTransfer(HTU_I2C, I2CInfo.address, (uint8_t)(number), I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_READ);
  32.    

  33.     for(read_Num = 0; read_Num < temp; read_Num++)
  34.   {
  35.     I2CInfo.timeout = I2C_LONG_TIMEOUT;
  36.     while(I2C_ReadStatusFlag(HTU_I2C, I2C_FLAG_RXBNE) == RESET)
  37.     {
  38.       if((I2CInfo.timeout--) == 0)
  39.       {
  40.         errSta = I2C_TIMEOUT;
  41.                                  return I2C_Callback(14);
  42.       }
  43.     }

  44.     buffer[read_Num] = I2C_RxData(HTU_I2C);
  45.   }
  46.     I2CInfo.timeout = I2C_LONG_TIMEOUT;
  47.     while(I2C_ReadStatusFlag(HTU_I2C, I2C_FLAG_STOP) == RESET)
  48.     {
  49.         if((I2CInfo.timeout--) == 0)
  50.         {
  51.             errSta = I2C_TIMEOUT;
  52.             return I2C_Callback(15);
  53.         }
  54.     }
  55.    
  56.    I2C_ClearStatusFlag(HTU_I2C, I2C_FLAG_STOP);
  57.    
  58.     return errSta;
  59. }
然后配置对应的读数据函数和数据转换函数。
  1. float Htu_Measure(uint8_t _ucOrder)
  2. {
  3.         uint8_t ucaRecvBuf[2] = {0};
  4.         uint8_t ucTmpVal = _ucOrder;
  5.         volatile float fTemp = 0.0;
  6.         volatile float fHumi = 0.0;
  7.         volatile float fRetVal = 0.0;


  8.         I2C_HTU_Read(ucaRecvBuf,ucTmpVal,2);

  9.         ucaRecvBuf[1] &= 0xFC;                //设置分辨率,最低两位为0,温度:14位;湿度:12位        
  10.         fRetVal = (ucaRecvBuf[0] << 8) | ucaRecvBuf[1];        // MSB=(MSB<<=8)+LSB;即将MSB移位到高8位

  11.         if(_ucOrder == HTU_TEMP)
  12.         {
  13.                  fTemp = (175.72) * fRetVal / 65536 - 46.85;//温度:T= -46.85 + 175.72 * ST/2^16
  14.                  
  15.                  return fTemp;
  16.         }
  17.         else if(_ucOrder == HTU_HUMI)
  18.         {
  19.                  fHumi = (fRetVal * 125) / 65536 - 6.00;//湿度: RH%= -6 + 125 * SRH/2^16

  20.                  return fHumi;
  21.         }
  22.         else
  23.         {
  24.                 return 0;
  25.         }
  26. }
用串口输出,就得到了当前的温湿度值
90a9141732f5f2a71b33b41bb32c5d6.png

HTU21D数据手册.pdf (983.58 KB, 下载次数: 2) APM32F072_EVAL_SDK_v1.0 .zip (1.46 MB, 下载次数: 6)


评论

学习一下  发表于 2023-3-31 15:46
averyleigh 发表于 2023-4-8 22:01 | 显示全部楼层
软件模拟IIC还是使用硬件IIC,哪个更好
usysm 发表于 2023-4-8 22:08 | 显示全部楼层
硬件I2C 到底是不是个坑               
youtome 发表于 2023-4-9 14:08 | 显示全部楼层
硬件I2C能与软件I2C一起用一个I2C通道么
lzbf 发表于 2023-4-9 14:23 | 显示全部楼层
这个读写的速度可以到多少呢?              
hilahope 发表于 2023-4-9 15:16 | 显示全部楼层
硬件II2C和软件I2C有什么区别
backlugin 发表于 2023-4-9 15:25 | 显示全部楼层
APM32F072的硬件I2C稳定吗
dspmana 发表于 2023-4-9 15:32 | 显示全部楼层
硬件iic应答失败如何自动恢复
chenci2013 发表于 2023-4-9 15:39 | 显示全部楼层
有硬件IIC,为什么很多应用,还要模拟IIC
 楼主| Alden 发表于 2023-5-6 17:14 | 显示全部楼层
averyleigh 发表于 2023-4-8 22:01
软件模拟IIC还是使用硬件IIC,哪个更好

硬件IIC速度更快,不占用CPU资源。模拟IIC更灵活,更方便移植。
 楼主| Alden 发表于 2023-5-6 17:15 | 显示全部楼层
backlugin 发表于 2023-4-9 15:25
APM32F072的硬件I2C稳定吗

测试还挺稳定的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

115

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部