当前位置: 首页 > news >正文

STM32CubeMX + HAL 库:基于 I²C 通信的 AHT20 高精度温湿度测量实验

 1 概述

1.1 实验目的

        本实验基于 STM32CubeMX 与 HAL 库,借助硬件 I²C 接口实现对 AHT20 高精度温湿度传感器的测量与数据处理。实验内容涵盖 AHT20 的初始化流程、指令交互机制、测量数据的采集与物理量转换等关键环节。通过对实验驱动代码与测试结果的完整展示,读者不仅能够深入理解 STM32 硬件 I²C 总线的应用方法,还能掌握数字环境传感器的通信特性及工程集成方式,为智能硬件系统中的 环境监测、气象采集与物联网应用 提供实践参考与技术支撑。

1.2 温湿度传感器介绍

        除常见的温湿度传感器外,部分器件也具备温度测量功能。例如,实时时钟芯片 DS3231 内部集成了一个温度传感器,用于实现晶振的温度补偿功能。虽然该传感器可以提供温度数据输出,但其设计主要目的是保证时钟的高精度运行,因此在实际应用中温度测量精度有限(典型精度约 ±3 ℃),不适合用于对环境温度有高精度要求的场景。

        此外,STM32 单片机内部也集成了温度传感器,通常位于片上二极管或晶体管结构,通过测量 PN 结电压随温度变化的特性来获得温度信息。该传感器的主要用途是为 MCU 的内部自适应调节和过热保护提供参考,其测量误差通常在 ±5 ℃ 甚至更大,且需要经过标定才能获得较为可靠的数据。因此,STM32 内部温度传感器更适合作为片内温度监测或过热保护手段,而不适合用于精确的环境温度采集。

型号通信接口工作电压温度范围温度精度湿度范围湿度精度分辨率响应时间特点
DHT11单总线3.3 ~ 5 V0 ~ 50 ℃±2 ℃20 ~ 90 %RH±5 %RH8 bit1 s成本低,性能一般,适合入门实验
DHT22 / AM2302单总线3.3 ~ 6 V-40 ~ 80 ℃±0.5 ℃0 ~ 100 %RH±2 ~ 5 %RH16 bit2 s精度高于 DHT11,但刷新率较低
AHT20I²C2.0 ~ 5.5 V-40 ~ 85 ℃±0.3 ℃0 ~ 100 %RH±2 %RH16 bit80 ms低功耗,小体积,高精度,替代 DHT 系列
SHT30I²C2.4 ~ 5.5 V-40 ~ 125 ℃±0.3 ℃0 ~ 100 %RH±2 %RH14 bit8 s瑞士 Sensirion 出品,稳定性高
SHT31I²C2.4 ~ 5.5 V-40 ~ 125 ℃±0.3 ℃0 ~ 100 %RH±2 %RH14 bit2 sSHT30 升级版,支持更快采样
Si7021I²C1.9 ~ 3.6 V-40 ~ 125 ℃±0.4 ℃0 ~ 100 %RH±3 %RH14 bit<10 ms美国 Silicon Labs 出品,超低功耗
DS3231 内部温度传感器I²C2.3 ~ 5.5 V-40 ~ 85 ℃±3 ℃10 bit~1 s用于晶振温度补偿,温度精度有限
STM32 内部温度传感器片内 ADC1.8 ~ 3.6 V-40 ~ 125 ℃±5 ℃(需校准)12 bit用于芯片过热保护,环境测量精度差

1.3 AHT20指标介绍

参数指标数值说明
供电电压 (VDD)2.0 ~ 5.5 V典型值 3.3 V
工作电流0.4 mA(测量时典型值)休眠电流 < 0.5 μA
通信接口I²C(标准模式/快速模式)最大速率 400 kHz
测量分辨率16 bit温度/湿度均为 16 位 ADC
湿度测量范围0 %RH ~ 100 %RH无凝露情况下
湿度测量精度±2 %RH(25 ℃时典型值)20%RH ~ 80%RH 区间
湿度重复性±0.1 %RH
温度测量范围-40 ℃ ~ +85 ℃
温度测量精度±0.3 ℃(25 ℃时典型值)-20 ℃ ~ +60 ℃ 区间
温度重复性±0.1 ℃
测量时间约 80 ms启动测量到输出数据
数据输出格式20 bit 有效数据(温度/湿度各占 20 位)通过 I²C 读取 6 字节数据
封装形式SMD 6 引脚小体积、贴片封装

注: 入门实验可使用 DHT11 或 DHT22 进行温湿度采集,二者通信兼容,DHT22 精度更高;实际工程或环境监测广泛使用 AHT20,高精度可靠;DS3231 与 STM32 内部温度传感器仅作辅助参考,不适合精确环境测量。

1.4 AHT20使用介绍

        在 STM32 HAL 库中,AHT20 的 7 位 I²C 地址固定为 0x38,左移 1 位得到 0x70。无论读写操作,只需在 HAL 函数中传入 0x70,HAL库会根据函数类型自动设置最低位(0=写,1=读)

步骤目的I²C 命令数据/参数延时备注
1初始化传感器0xE10x08 0x0040ms进入正常工作模式
2读取状态(可选)读取 1 字节状态寄存器
  • bit3 (CALIB) = 1 → 表示校准完成,初始化成功

  • bit7 (BUSY) = 0 → 表示传感器空闲

3软件复位(Soft Reset)0xBA20ms可选步骤,用于强制复位传感器
4发送测量命令0xAC0x33 0x0080ms启动一次温湿度测量
5读取测量数据读取 6 字节前 20bit:湿度;后 20bit:温度,需要解析成浮点值

1.5 写命令

在 HAL 库中,有两个常用 I²C 函数发送数据:

写数据 (HAL_I2C_Mem_Write)

HAL_I2C_Mem_Write

  • 场景:适用于存储型 I²C 设备(如 EEPROM)

  • 功能:一次性写入内存地址和数据

  • 特点:保证总线时序连续,EEPROM 或寄存器型芯片可以正确识别存储地址

注意事项

  • 不能分两次使用 HAL_I2C_Master_Transmit

  • 原因:第一次发送存储地址后 Stop → 第二次发送数据时,EEPROM 会把第一个数据字节当作新的内存地址

  • 正确做法:一次性发送 [存储地址 + 数据],或使用 HAL_I2C_Mem_Write

内部实现

  • Start 信号:主机发送起始信号

  • 发送从机地址 + 写标志 (DevAddr+W)

  • 发送存储地址 (MemAddress)

  • 发送数据:从机接收要写入的字节

  • Stop 信号:结束总线通信


传输数据 (HAL_I2C_Master_Transmit)

HAL_I2C_Master_Transmit

  • 场景:适用于命令型 I²C 设备(如 AHT20)

  • 功能:发送命令及参数数据

  • 特点:可先发送命令,再连续发送参数,效果等同于 HAL_I2C_Mem_Write

  • 原因:HAL 库底层写操作就是“先发送地址/命令 → 再发送数据”,总线连续

内部实现

  • Start 信号:主机发送起始信号

  • 发送从机地址 + 写标志 (DevAddr+W)

  • 发送命令字

  • 发送参数数据(可选)

  • Stop 信号:结束总线通信

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c,      // 指向 I2C 外设句柄,选择具体 I2C(如 &hi2c1)uint16_t DevAddress,           // 从设备 I²C 地址(左移1位的8位地址),HAL 自动处理 R/W 位uint16_t MemAddress,           // 从设备内部寄存器地址(要写入的寄存器)uint16_t MemAddSize,           // 寄存器地址长度:I2C_MEMADD_SIZE_8BIT 或 I2C_MEMADD_SIZE_16BITuint8_t *pData,                // 指向要写入的数据缓冲区指针uint16_t Size,                 // 要写入的数据长度(字节数)uint32_t Timeout               // 超时时间(ms),超过返回错误
);
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c,  // I2C 外设句柄uint16_t DevAddress,       // 从机地址(7 位或 10 位地址左移 + R/W 位)uint8_t *pData,            // 待发送的数据缓冲区指针uint16_t Size,             // 发送的数据长度(字节数)uint32_t Timeout           // 超时时间(ms)
);

1.6 读数据

在 HAL 库中,有两个常用 I²C 函数接收数据:

读数据 (HAL_I2C_Mem_Read)

  • 场景:适合带内部地址或寄存器的 I²C 设备

  • 功能:先写从机内部寄存器地址,再读取数据

  • 特点:通过写入寄存器地址 + Repeated Start + 读操作,保证时序连续,适用于带寄存器或内存地址的 I²C 设备(如 EEPROM)

内部实现

  • Start 信号:主机发送起始信号

  • 发送从机地址 + 写标志 (DevAddr+W)

  • 发送寄存器/存储地址 (MemAddress)

  • Repeated Start 信号:连续启动,保持总线控制权

  • 发送从机地址 + 读标志 (DevAddr+R)

  • 接收数据:从从机读取指定长度的数据

  • Stop 信号:结束总线通信

说明:这种操作保证了时序连续,EEPROM 或寄存器型 I²C 芯片可以安全识别寄存器地址并返回正确数据。

接收数据 (HAL_I2C_Master_Receive)

  • 场景:适合命令型设备直接返回数据或连续读取 I²C 总线数据

  • 功能:直接从 I²C 从机接收指定长度的数据

  • 特点:无需先写寄存器地址,数据读取连续,适用于不带内部寄存器地址的设备(如 AHT20 测量数据)

内部实现

  1. Start 信号:主机发送起始信号

  2. 发送从机地址 + 读标志 (DevAddr+R)

  3. 接收数据:从从机连续读取指定长度的数据

  4. Stop 信号:结束总线通信

说明:因为没有写入寄存器地址的过程,所以 EEPROM 等需要先指定内存地址的芯片不能直接使用该函数读取数据。

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c,  // 指向 I2C 外设句柄,选择具体 I2C(如 &hi2c1)uint16_t DevAddress,       // 从设备 I²C 地址(左移1位的8位地址),HAL 自动处理 R/W 位uint8_t *pData,            // 指向接收数据缓冲区的指针uint16_t Size,             // 要接收的数据长度(字节数)uint32_t Timeout           // 超时时间(ms),超过返回错误
);
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c,  // I2C 外设句柄uint16_t DevAddress,       // I2C 从机地址(7 位左移 + R/W)uint16_t MemAddress,       // 内存寄存器地址 / 命令字uint16_t MemAddSize,       // MemAddress 长度:I2C_MEMADD_SIZE_8BIT 或 I2C_MEMADD_SIZE_16BITuint8_t *pData,            // 接收数据缓冲区指针uint16_t Size,             // 要接收的数据长度(字节数)uint32_t Timeout           // 超时时间(ms)
);

2. STM32CubeMx设置

2.1 SYS设置

2.2 RCC设置

2.3 IIC设置

2.4 USART设置

3. MDK keil设置

3.1 Target设置

3.2 工程目录添加

3.3 debug设置

3.4 工程文件添加

4. VSCode编码

4.1 ATH20.c

#include "ATH20.h"
#include "stm32f1xx_hal.h"
#include "stdio.h"
#include "string.h"/*** * @brief 初始化完成检测* @retval 1: 初始化完成, 0: 未完成*/
uint8_t ATH20_Read_Cal_Init_Enable(void)
{uint8_t status = 0;HAL_I2C_Master_Receive(&hi2c1, ATH20_SLAVE_ADDRESS, &status, 1, HAL_MAX_DELAY);// CALIB = 1if((status & 0x08) != 0)return 1;elsereturn 0;
}/*** @brief 测量完成检测* @retval 1: 测量完成, 0: 测量中*/
uint8_t ATH20_Read_Cal_Test_Enable(void)
{uint8_t status = 0;HAL_I2C_Master_Receive(&hi2c1, ATH20_SLAVE_ADDRESS, &status, 1, HAL_MAX_DELAY);// BUSY = 0 表示测量完成return ((status & 0x80) == 0) ? 1 : 0;
}/*** @brief  初始化 AHT20* @retval 0 成功,1 失败*/
uint8_t ATH20_Init(void)
{uint8_t cmd = INIT;uint8_t param[2] = {0x08, 0x00};uint8_t count = 0;// 初始化传感器 HAL_I2C_Mem_Write(&hi2c1, ATH20_SLAVE_ADDRESS, INIT, I2C_MEMADD_SIZE_8BIT, param, 2, HAL_MAX_DELAY);// HAL_I2C_Master_Transmit(&hi2c1, ATH20_SLAVE_ADDRESS, &cmd, 1, HAL_MAX_DELAY);//先发送命令字// HAL_I2C_Master_Transmit(&hi2c1, ATH20_SLAVE_ADDRESS, param, 2, HAL_MAX_DELAY);// 再发送参数HAL_Delay(40);// 等待校准完成while (!ATH20_Read_Cal_Init_Enable()){// 软件复位uint8_t reset = SoftReset;HAL_I2C_Master_Transmit(&hi2c1, ATH20_SLAVE_ADDRESS, &reset, 1, HAL_MAX_DELAY);HAL_Delay(20);// 再次初始化HAL_I2C_Mem_Write(&hi2c1, ATH20_SLAVE_ADDRESS, INIT, I2C_MEMADD_SIZE_8BIT, param, 2, HAL_MAX_DELAY);// HAL_I2C_Master_Transmit(&hi2c1, ATH20_SLAVE_ADDRESS, &cmd, 1, HAL_MAX_DELAY);// HAL_I2C_Master_Transmit(&hi2c1, ATH20_SLAVE_ADDRESS, param, 2, HAL_MAX_DELAY);HAL_Delay(40);if (++count >= 10){printf("AHT20 init failed after 10 attempts\r\n");return 0; // 初始化失败}}printf("AHT20 initialization successful\r\n");return 1; // 初始化成功
}/*** @brief  读取温湿度数据* @param  temp: 温度指针 (单位 ℃)* @param  humidity: 湿度指针 (单位 %)*/
void ATH20_Read_CTdata(float *temp, float *humidity)
{uint8_t cmd[2] = {0x33, 0x00}; // 测量命令参数uint8_t buf[6] = {0};// 发送测量命令HAL_I2C_Mem_Write(&hi2c1, ATH20_SLAVE_ADDRESS, StartTest, I2C_MEMADD_SIZE_8BIT, cmd, 2, HAL_MAX_DELAY);HAL_Delay(80);// 等待测量完成while(!ATH20_Read_Cal_Test_Enable()) {HAL_Delay(5);  // 每 5ms 查询一次状态寄存器}// 测量完成后读取 6 字节数据if(HAL_I2C_Master_Receive(&hi2c1, ATH20_SLAVE_ADDRESS, buf, 6, HAL_MAX_DELAY) != HAL_OK){*temp = 0;*humidity = 0;return;}// 数据解析uint32_t raw_hum = ((uint32_t)(buf[1]) << 12) | ((uint32_t)(buf[2]) << 4) | ((buf[3] >> 4) & 0x0F);uint32_t raw_temp = (((uint32_t)(buf[3] & 0x0F)) << 16) | ((uint32_t)(buf[4]) << 8) | buf[5];*humidity = (float)raw_hum * 100.0f / 1048576.0f;*temp = (float)raw_temp * 200.0f / 1048576.0f - 50.0f;
}

4.2 ATH20.h

#ifndef __ATH20_H
#define __ATH20_H#include "stm32f1xx_hal.h"// I2C 句柄
extern I2C_HandleTypeDef hi2c1;#define ATH20_SLAVE_ADDRESS    (0x38 << 1)   // HAL 库使用 8 位地址,需要左移1
// AHT20 命令
#define INIT        0xE1    // 初始化
#define SoftReset   0xBA    // 软件复位
#define StartTest   0xAC    // 启动测量uint8_t ATH20_Init(void);
uint8_t ATH20_Read_Cal_Init_Enable(void);
uint8_t ATH20_Read_Cal_Test_Enable(void);
void ATH20_Read_CTdata(float *temp, float *humidity);#endif

4.3 usart.c

/* USER CODE BEGIN Header */
/********************************************************************************* @file    usart.c* @brief   This file provides code for the configuration*          of the USART instances.******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */UART_HandleTypeDef huart1;/* USART1 init function */void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 4, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPA9     ------> USART1_TXPA10     ------> USART1_RX*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
int fputc(int ch, FILE * file){ //打印重定向HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,1000);return ch;
}
/* USER CODE END 1 */

4.4 usart.h

/* USER CODE BEGIN Header */
/********************************************************************************* @file    usart.h* @brief   This file contains all the function prototypes for*          the usart.c file******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__#ifdef __cplusplus
extern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "main.h"/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */extern UART_HandleTypeDef huart1;/* USER CODE BEGIN Private defines *//* USER CODE END Private defines */void MX_USART1_UART_Init(void);/* USER CODE BEGIN Prototypes *//* USER CODE END Prototypes */#ifdef __cplusplus
}
#endif#endif /* __USART_H__ */

4.5 main.c

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ATH20.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
float temper, humidity; //ATH20输出参数
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_I2C1_Init();/* USER CODE BEGIN 2 */if (ATH20_Init()){printf("AHT20 Init OK!\r\n");}else{printf("AHT20 Init Failed!\r\n");while (1);}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */// 温湿度读取ATH20_Read_CTdata(&temper, &humidity);printf("Temp: %.2f C, Humidity: %.2f %%\r\n", temper, humidity);HAL_Delay(3000);}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

5. 验证

        通过对 AHT20 传感器吹气,可以明显观察到温度和湿度的上升,传感器响应非常灵敏。本实验采用 I²C 通信实现数据采集。与存储型 EEPROM(如 AT24C32)不同,AHT20 属于命令型设备,因此在使用 STM32 HAL 库时的函数调用方式有所区别。本实验不仅巩固了 I²C 通信的基本知识和 HAL 库函数的使用方法,同时也对高精度温湿度传感器的应用进行了实践说明,为学习和工作提供了参考。

http://www.xdnf.cn/news/1395361.html

相关文章:

  • 【系列03】端侧AI:构建与部署高效的本地化AI模型 第2章:端侧AI硬件入门
  • 134-细粒度多尺度符号熵和鲸鱼优化算法的滚动轴承故障诊断技术MSVM
  • Redis搭建哨兵模式一主两从三哨兵
  • 线程安全及死锁问题
  • 【好题推荐】运算符的构造运用
  • 光伏发多少电才够用?匹配家庭用电需求
  • #医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(五)
  • Linux内核进程管理子系统有什么第三十八回 —— 进程主结构详解(34)
  • JUC并发编程09 - 内存(01) - JMM/cache
  • 嵌入式Linux设备树驱动开发 - dtsof驱动
  • Unity DateTime 相关
  • 处理器(CPU/MPU)的双发射是什么?
  • 命令扩展与重定向
  • 可解释人工智能XAI
  • 【机器学习深度学习】Embedding 与 RAG:让 AI 更“聪明”的秘密
  • leetcode 191 位1的个数
  • 【0422】SMgrRelationData 中 md_num_open_segs 和 md_seg_fds 数组为什么是 4 个元素? 第四个元素表示什么?
  • Ubuntu磁盘分区重新挂载读写指南
  • 不一样的发票管理模式-发票识别+发票查验接口
  • ContextMenuManager for Win:优化右键菜单,解决用户痛点
  • lxml库如何使用
  • ElasticSearch对比Solr
  • C语言————操作符详解
  • TypeScript的Type
  • MySQL 中如果发生死锁应该如何解决?
  • 每日算法题【二叉树】:对称二叉树、二叉树的前中后序遍历
  • 回车换行、缓冲区刷新、倒计时小程序
  • MQTT高延迟通信优化指南
  • Python的Listd 数据格式 V0.1
  • 深入解析Nginx核心模块