[开发工具] STM32CubeMX_15 | 使用硬件I2C读取温湿度传感器数据(SHT30)

[复制链接]
1976|39
 楼主| alternate 发表于 2020-4-9 10:24 | 显示全部楼层
注意数据手册中给出了8位数据,只有低7位用作地址,结合原理图,可以定义如下:

  1. /* ADDR Pin Conect to VSS */

  2. #define    SHT30_ADDR_WRITE    0x44<<1         //10001000
  3. #define    SHT30_ADDR_READ     (0x44<<1)+1        //10001011
 楼主| alternate 发表于 2020-4-9 10:24 | 显示全部楼层
枚举SHT30命令列表
参考数据手册,在sht30_i2c_drv.h头文件中给出如下枚举定义:

  1. typedef enum
  2. {
  3.     /* 软件复位命令 */

  4.     SOFT_RESET_CMD = 0x30A2,   
  5.     /*
  6.     单次测量模式
  7.     命名格式:Repeatability_CS_CMD
  8.     CS: Clock stretching
  9.     */
  10.     HIGH_ENABLED_CMD    = 0x2C06,
  11.     MEDIUM_ENABLED_CMD  = 0x2C0D,
  12.     LOW_ENABLED_CMD     = 0x2C10,
  13.     HIGH_DISABLED_CMD   = 0x2400,
  14.     MEDIUM_DISABLED_CMD = 0x240B,
  15.     LOW_DISABLED_CMD    = 0x2416,

  16.     /*
  17.     周期测量模式
  18.     命名格式:Repeatability_MPS_CMD
  19.     MPS:measurement per second
  20.     */
  21.     HIGH_0_5_CMD   = 0x2032,
  22.     MEDIUM_0_5_CMD = 0x2024,
  23.     LOW_0_5_CMD    = 0x202F,
  24.     HIGH_1_CMD     = 0x2130,
  25.     MEDIUM_1_CMD   = 0x2126,
  26.     LOW_1_CMD      = 0x212D,
  27.     HIGH_2_CMD     = 0x2236,
  28.     MEDIUM_2_CMD   = 0x2220,
  29.     LOW_2_CMD      = 0x222B,
  30.     HIGH_4_CMD     = 0x2334,
  31.     MEDIUM_4_CMD   = 0x2322,
  32.     LOW_4_CMD      = 0x2329,
  33.     HIGH_10_CMD    = 0x2737,
  34.     MEDIUM_10_CMD  = 0x2721,
  35.     LOW_10_CMD     = 0x272A,
  36.     /* 周期测量模式读取数据命令 */
  37.     READOUT_FOR_PERIODIC_MODE = 0xE000,
  38. } SHT30_CMD;
 楼主| alternate 发表于 2020-4-9 10:25 | 显示全部楼层
发送命令函数

  1. /**
  2. * [url=home.php?mod=space&uid=247401]@brief[/url]    向SHT30发送一条指令(16bit)
  3. * @param    cmd —— SHT30指令(在SHT30_MODE中枚举定义)
  4. * @retval    成功返回HAL_OK
  5. */
  6. static uint8_t    SHT30_Send_Cmd(SHT30_CMD cmd)
  7. {
  8.     uint8_t cmd_buffer[2];
  9.     cmd_buffer[0] = cmd >> 8;
  10.     cmd_buffer[1] = cmd;
  11.     return HAL_I2C_Master_Transmit(&hi2c1, SHT30_ADDR_WRITE, (uint8_t* cmd_buffer, 2, 0xFFFF);
  12. }
 楼主| alternate 发表于 2020-4-9 10:25 | 显示全部楼层
复位函数

  1. /**
  2. * @brief    复位SHT30
  3. * @param    none
  4. * @retval    none
  5. */
  6. void SHT30_reset(void)
  7. {
  8.     SHT30_Send_Cmd(SOFT_RESET_CMD);
  9.     HAL_Delay(20);
  10. }
 楼主| alternate 发表于 2020-4-9 10:26 | 显示全部楼层
SHT30工作模式初始化函数(周期测量模式)

  1. /**
  2. * @brief    初始化SHT30
  3. * @param    none
  4. * @retval    成功返回HAL_OK
  5. * [url=home.php?mod=space&uid=536309]@NOTE[/url]    周期测量模式
  6. */
  7. uint8_t SHT30_Init(void)
  8. {
  9.     return SHT30_Send_Cmd(MEDIUM_2_CMD);
  10. }
 楼主| alternate 发表于 2020-4-9 10:26 | 显示全部楼层
从SHTY30读取一次数据(周期测量模式下)
从SHT30数据手册中可以得到在周期测量模式下读取一次数据的时序,如图:
952225e8e87d32a929.png
 楼主| alternate 发表于 2020-4-9 10:27 | 显示全部楼层
根据该时序可以看出,首先要发送读数据的命令,然后接收6个字节的数据,编写程序如下:

  1. /**
  2. * @brief    从SHT30读取一次数据
  3. * @param    dat —— 存储读取数据的地址(6个字节数组)
  4. * @retval    成功 —— 返回HAL_OK
  5. */
  6. uint8_t SHT30_Read_Dat(uint8_t* dat)
  7. {
  8.     SHT30_Send_Cmd(READOUT_FOR_PERIODIC_MODE);
  9.     return HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR_READ, dat, 6, 0xFFFF);
  10. }
 楼主| alternate 发表于 2020-4-9 10:28 | 显示全部楼层
从接收数据中校验并解析温度值和湿度值
在数据手册中可知,SHT30分别在温度数据和湿度数据之后发送了8-CRC校验码,确保了数据可靠性。

关于CRC校验请参考我的另一篇博客:如何通俗的理解CRC校验并用C语言实现。
 楼主| alternate 发表于 2020-4-9 10:28 | 显示全部楼层
CRC-8校验程序如下:

  1. #define CRC8_POLYNOMIAL 0x31

  2. uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
  3. {
  4.     uint8_t  remainder;        //余数
  5.     uint8_t  i = 0, j = 0;  //循环变量

  6.     /* 初始化 */
  7.     remainder = initial_value;

  8.     for(j = 0; j < 2;j++)
  9.     {
  10.         remainder ^= message[j];

  11.         /* 从最高位开始依次计算  */
  12.         for (i = 0; i < 8; i++)
  13.         {
  14.             if (remainder & 0x80)
  15.             {
  16.                 remainder = (remainder << 1)^CRC8_POLYNOMIAL;
  17.             }
  18.             else
  19.             {
  20.                 remainder = (remainder << 1);
  21.             }
  22.         }
  23.     }

  24.     /* 返回计算的CRC码 */
  25.     return remainder;
  26. }
 楼主| alternate 发表于 2020-4-9 10:29 | 显示全部楼层
计算温度值和湿度值的公式在数据手册中已给出,如图:

940025e8e88745f7a9.png
 楼主| alternate 发表于 2020-4-9 10:29 | 显示全部楼层
接下来编写解析数据的函数:

  1. /**
  2. * @brief    将SHT30接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
  3. * @param    dat  —— 存储接收数据的地址(6个字节数组)
  4. * @retval    校验成功  —— 返回0
  5. *             校验失败  —— 返回1,并设置温度值和湿度值为0
  6. */
  7. uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity)
  8. {
  9.     uint16_t recv_temperature = 0;
  10.     uint16_t recv_humidity = 0;

  11.     /* 校验温度数据和湿度数据是否接收正确 */
  12.     if(CheckCrc8(dat, 0xFF) != dat[2] || CheckCrc8(&dat[3], 0xFF) != dat[5])
  13.         return 1;

  14.     /* 转换温度数据 */
  15.     recv_temperature = ((uint16_t)dat[0]<<8)|dat[1];
  16.     *temperature = -45 + 175*((float)recv_temperature/65535);

  17.     /* 转换湿度数据 */
  18.     recv_humidity = ((uint16_t)dat[3]<<8)|dat[4];
  19.     *humidity = 100 * ((float)recv_humidity / 65535);

  20.     return 0;
  21. }
 楼主| alternate 发表于 2020-4-9 10:30 | 显示全部楼层
5. 测试SHT30驱动程序
在main函数中对该驱动进行测试,在main.c中添加如下代码:

  1. #include <stdio.h>
  2. #include "sht30_i2c_drv.h"

  3. int main(void)
  4. {
  5.     /* USER CODE BEGIN 1 */
  6.     uint8_t recv_dat[6] = {0};
  7.     float temperature = 0.0;
  8.     float humidity = 0.0;
  9.     /* USER CODE END 1 */

  10.     HAL_Init();

  11.     SystemClock_Config();

  12.     MX_GPIO_Init();
  13.     MX_I2C1_Init();
  14.     MX_USART1_UART_Init();

  15.     /* USER CODE BEGIN 2 */
  16.     SHT30_Reset();
  17.     if(SHT30_Init() == HAL_OK)
  18.         printf("sht30 init ok.\n");
  19.     else
  20.         printf("sht30 init fail.\n");
  21.   /* USER CODE END 2 */

  22.   /* Infinite loop */
  23.   /* USER CODE BEGIN WHILE */
  24.   while (1)
  25.   {
  26.     /* USER CODE END WHILE */

  27.     /* USER CODE BEGIN 3 */
  28.         HAL_Delay(1000);
  29.         if(SHT30_Read_Dat(recv_dat) == HAL_OK)
  30.         {
  31.             if(SHT30_Dat_To_Float(recv_dat, &temperature, &humidity)==0)
  32.             {
  33.                 printf("temperature = %f, humidity = %f\n", temperature, humidity);
  34.             }
  35.             else
  36.             {
  37.                 printf("crc check fail.\n");
  38.             }
  39.         }
  40.         else
  41.         {
  42.             printf("read data from sht30 fail.\n");
  43.         }
  44.     }
  45.   /* USER CODE END 3 */
  46. }
 楼主| alternate 发表于 2020-4-9 10:30 | 显示全部楼层
测试结果如图:

493875e8e88ce937e3.png
 楼主| alternate 发表于 2020-4-9 10:31 | 显示全部楼层
至此,我们已经学会如何使用硬件IIC接口读取温湿度传感器数据并使用软件CRC校验(SHT30),下一节将讲述如何使用硬件CRC校验SHT30的数据。
keaibukelian 发表于 2020-5-7 13:18 | 显示全部楼层
非常感谢楼主分享
labasi 发表于 2020-5-7 13:19 | 显示全部楼层
这种传感器精度能达到多少呢
paotangsan 发表于 2020-5-7 13:41 | 显示全部楼层
基本上都差不多
renzheshengui 发表于 2020-5-7 13:43 | 显示全部楼层
小数点后位数好多啊
wakayi 发表于 2020-5-7 13:43 | 显示全部楼层
非常详细 感谢楼主
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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