傳感器:基于STM32F103/407系AHT20溫濕度傳感器數據采集

一、IIC總線

1、IIC總線概念

??I2C(Inter-Integrated Circuit)總線是由PHILIPS公司開發的兩線式串行總線,用于連接微控制器及其外圍設備。是微電子通信控制領域廣泛采用的一種總線標準。它是同步通信的一種特殊形式,具有接口線少,控制方式簡單,器件封裝形式小,通信速率較高等優點。I2C總線只有兩根雙向信號線。一根是數據線SDA,另一根是時鐘線SCL。由于其管腳少,硬件實現簡單,可擴展性強等特點,因此被廣泛的使用在各大集成芯片內。

1.1、IIC總線分類

??作為用戶如何使用IIC?那就首先明確IIC的分類,從使用上看,可以分為硬件IIC和軟件IIC
(1)硬件IIC
??硬件IIC是指對于一些高度集成化的芯片中集成了IIC總線,例如:STM32單片機芯片就集成了IIC總線(類似于AHB總線、APB總線等等);用戶使用硬件IIC相對來說操作簡單,只需要在芯片上配置IIC總線(例如:在STM32CubeMX/STM32CubeIDE和上配置即可生成IIC初始化代碼)之后,調用相應的IIC通信API即可實現IIC通信,這種方式雖簡單,但是往往很多初學者掌握不了IIC總線時序,實際面試中很難回答出IIC總線時序,導致拿不到心儀的offer,故作者建議,在不考慮通信速率情況下(硬件算力始終比軟件算力更快速),選擇軟件IIC來實現。
在這里插入圖片描述
(2)軟件IIC
??軟件IIC是指通過芯片的引腳來模擬IIC總線要求的時序,達到通過模擬IIC總線來完成IIC通信的目的。通過軟件模擬IIC總線時序,用戶可以深刻掌握IIC總線核心概念起始信號、數據有效性、應答/非應答信號、停止信號等,建議初學者通過這種方式來學習IIC總線,等IIC總線掌握成熟之后,后期可以根據項目情況選擇硬件IIC還是軟件IIC。

1.2、IIC總線引腳

??IIC總線是由兩根線組成,分別是時鐘信號線和數據總線,IIC通信就靠這兩根線實現
(1)時鐘信號線
??單詞:serial clock,簡稱:SCL
??該線是用于收、發雙方兩個設備之間數據的同步,即發送方發送數據時需要通過時鐘信號線告訴接收方(例如:你要去你朋友家做客,你首先提前告訴你朋友,你朋友知道你要來之后,就開始準備飯菜等待你過來),從這里可以看出IIC總線通信實質上是一種同步通信(常用的串口UART是一種異步通信)
(2)數據總線
??單詞:serial data,簡稱:SDA
??該線是用于收、發雙方兩個設備之間數據的傳輸,即發送方發送數據時需要通過數據總線發送給接收方(例如:你要去你朋友家做客,你提前告訴給你朋友時是通過什么方式告訴給你朋友,企鵝?微信?還是其他的通道等)

1.3、IIC總線尋址

??IIC總線尋址方式默認有兩種,分別是7位尋址和10位尋址,但大多數IIC總線設備采用7位尋址。
(1)7位
??7位是指地址的表示為7個bit(即共2^7=128個設備地址),但有些廠家在生產設備時往往會將7bit里的部分bit設置為固定,剩余部分預留為可供用戶編程來實現確定設備地址。
??例如OLED屏幕地址如下:
??????在這里插入圖片描述
??b2-b7這6位廠家設置為固定,b1和b0是可編程位,用戶可以根據實際情況對b0和b1進行編程設置。
(2)尋址
??尋址是指尋找地址,即主設備與掛接在IIC總線上的設備進行通信時,需要知道設備的地址(注:掛接在IIC總線上設備有唯一地址,如果不唯一則通信就會紊亂,就好比一個班級里有2個名為張三的學生,老師請張三起來回答問題,到底是哪個張三起來回答問題?)。
(3)從設備地址表示
??從設備地址由7bit+1bit讀寫位組成,如果讀寫位1bit是0,則表示主設備向從設備寫數據,如果讀寫位1bit是1,則表示主設備從從設備讀數據。
例如:
??在這里插入圖片描述

1.4、IIC總線數據傳輸大小

??IIC總線數據傳輸是以字節byte為單位,即一個字節=8bit,每次傳輸的字節數量無限制,根據實際情況進行傳輸即可。

2、IIC總線時序

??IIC總時序圖如下:
在這里插入圖片描述

2.1、起始信號(START Condition)

??是指數據發送開始的信號。

時序步驟:(1)SCL保持輸出高電平(2)SDA輸出高電平變為輸出低電平

2.2、停止信號(STOP Condition)

??是指數據發送停止的信號。

時序步驟:(1)SCL保持輸出高電平(2)SDA由輸出低電平變為輸出高電平

2.3、數據有效性(DATA Validation)

??是指數據在收、發雙方之間傳輸時什么時候是穩定可靠的,什么時候變化的。

時序步驟:(1)SCL輸出低電平(2)SDA讀取/輸出電平(3)SCL輸出高電平(4)SCL輸出低電平

2.4、應答/非應答信號(ACK/NACK)

??是指接收方是否接收到發送方發送的數據,需要給發送方的一個應答信號,如果接收到(也可以理解為數據接收正確),則應答(ACK);反之,則不應答(NACK)。根據IIC總線時序,如果SDA讀取為低電平0,則是應答(ACK)信號,如果SDA讀取為高電平1,則是非應答(NACK)信號

時序步驟:(1)SCL輸出低電平(2)SDA讀取/輸出電平(3)SCL輸出高電平(4)SCL輸出低電平

3、AHT20概念

??AHT20溫濕度傳感器嵌入了適于回流焊的雙列扁平無引腳SMD封裝,傳感器輸出經過標定的數字信號,標準IIC格式。AHT20配有ASIC專用芯片、MEMS半導體電容式濕度傳感元件和片上溫度傳感元件,使其性能大大提升,每一個傳感器都經過校準和測試,并印有產品批號。
??廣泛應用于智能家居、消費電子、醫療、汽車、工業、氣象等領域,例如:暖通空調、除濕器和冰箱等家電產品,測試和檢測設備及其他相關溫濕度檢測產品。

3.1、AHT20重置指令

指令代碼:0x70(AHT20設備寫地址)0xBA(AHT20軟件復位指令)

3.2、AHT20初始化指令

指令代碼:0x70(AHT20設備寫地址)0xE1(AHT20特殊狀態使用指令) 0x08(AHT20啟動初始化過程指令)0x00(AHT20輔助完成初始化過程指令)

3.3、AHT20狀態字節表示

??狀態字節表示如圖所示:
在這里插入圖片描述

3.4、AHT20溫度和濕度的表示

(1)濕度數據
??AHT20采集的濕度數據由20位(20bit)組成,由高位向低位進行采集。
濕度計算公式:
在這里插入圖片描述

(2)溫度數據
??AHT20采集的溫度數據由20位(20bit)組成,由高位向低位進行采集。
溫度計算公式:
??在這里插入圖片描述

3.5、AHT20溫濕度測量流程

步驟流程如下所示:
??(1)AHT20軟件重置(發送指令:0x70、0xBA)
??(2)AHT20初始化(發送指令:0x70、0xE1、0x08、0x00)
??(3)AHT20讀取溫濕度數據,如下圖流程
在這里插入圖片描述

4、STM32F407ZET6測量AHT20溫濕度源碼

4.1、AHT20.h

/*AHT20采用模擬IIC實現,初始需要在軟件STM32CubeMX或CubeIDE上將PF0和PF1設置為推挽輸出模式SCL引腳:PF1SDA引腳:PF0
*/
#include "stm32f4xx_hal.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#define IIC_SCL_HIGH() HAL_GPIO_WritePin(GPIOF,GPIO_PIN_1,GPIO_PIN_SET)
#define IIC_SCL_LOW() HAL_GPIO_WritePin(GPIOF,GPIO_PIN_1,GPIO_PIN_RESET)
#define IIC_SDA_HIGH() HAL_GPIO_WritePin(GPIOF,GPIO_PIN_0,GPIO_PIN_SET)
#define IIC_SDA_LOW() HAL_GPIO_WritePin(GPIOF,GPIO_PIN_0,GPIO_PIN_RESET)
#define IIC_SDA_READ() HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_0)
#define IIC_SDA_IN() {GPIOF->MODER &=~(3<<(0*2));GPIOF->MODER|=0<<0*2;}
#define IIC_SDA_OUT() {GPIOF->MODER &=~(3<<(0*2));GPIOF->MODER|=1<<0*2;}
//IIC時序API
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Master_ACK(void);
void IIC_Master_NACK(void);
unsigned char IIC_Slave_ACK_NACK(void);
void IIC_Write_Byte(unsigned char data);
unsigned char IIC_Read_Byte(void);
//AHT20API
struct AHT20_MSG
{unsigned char status;//狀態數據int temp;//溫度數據int hum;//濕度數據unsigned char crc;//校驗數據
};
void AHT20_Reset(void);
void AHT20_Init(void);
void AHT20_Measure(void);
struct AHT20_MSG * AHT20_Read_Temp_Hum(void);
void AHT20_Hum_Add(int *hum_array,unsigned char data);
void AHT20_Temp_Add(int *temp_array,unsigned char data);
void AHT20_Hum_Temp_Split(int *hum_array,int *temp_array,unsigned char data);
void AHT20_Display_Hum_Temp(struct AHT20_MSG *AHT20_P);

4.1、AHT20.c

#include "AHT20.h"
/*IIC起始信號
*/
void IIC_Start(void)
{IIC_SCL_HIGH();IIC_SDA_HIGH();IIC_SDA_LOW();
}
/*IIC停止信號
*/
void IIC_Stop(void)
{IIC_SCL_HIGH();IIC_SDA_LOW();IIC_SDA_HIGH();
}
/*IIC主機應答從機信號
*/
void IIC_Master_ACK(void)
{IIC_SCL_LOW();IIC_SDA_LOW();IIC_SCL_HIGH();IIC_SCL_LOW();
}
/*IIC主機不應答從機信號
*/
void IIC_Master_NACK(void)
{IIC_SCL_LOW();IIC_SDA_HIGH();IIC_SCL_HIGH();IIC_SCL_LOW();
}
/*IIC從機應答或不應答主機信號返回值:unsigned char,返回的是從機的應答/不應答信號
*/
unsigned char IIC_Slave_ACK_NACK(void)
{unsigned char ack=0;IIC_SCL_LOW();//將SDA引腳設置為輸入IIC_SDA_IN();IIC_SCL_HIGH();if(IIC_SDA_READ()){ack=1;}else{ack=0;}IIC_SCL_LOW();//將SDA引腳設置為輸出IIC_SDA_OUT();return ack;
}
/*IIC主機向從機寫一個字節數據參數:data,寫入的1byte數據
*/
void IIC_Write_Byte(unsigned char data)
{for(int i=0;i<8;i++){IIC_SCL_LOW();if(data&0x80){IIC_SDA_HIGH();IIC_SCL_HIGH();}else{IIC_SDA_LOW();	IIC_SCL_HIGH();			}IIC_SCL_LOW();data=data<<1;}
}
/*IIC主機從從機讀一個字節數據返回值:unsigned char,返回的是讀取到的1byte數據
*/
unsigned char IIC_Read_Byte(void)
{unsigned char data=0;IIC_SCL_LOW();
//	//將引腳設置為輸入IIC_SDA_IN();for(int i=0;i<8;i++){IIC_SCL_HIGH();data=data<<1;if(IIC_SDA_READ()){data+=1;}IIC_SCL_LOW();}
//	//將引腳設置為輸出IIC_SDA_OUT();return data;
}/*AHT20復位(重置)
*/
void AHT20_Reset(void)
{IIC_Start();IIC_Write_Byte(0x70);//AHT20從機地址IIC_Slave_ACK_NACK();//等待從機應答IIC_Write_Byte(0xBA);//復位命令IIC_Slave_ACK_NACK();//等待從機應答IIC_Stop();
}
/*AHT20初始化
*/
void AHT20_Init(void)
{IIC_Start();IIC_Write_Byte(0x70);//AHT20從機地址IIC_Slave_ACK_NACK();//等待從機應答IIC_Write_Byte(0xE1);IIC_Slave_ACK_NACK();//等待從機應答	IIC_Write_Byte(0x08);IIC_Slave_ACK_NACK();//等待從機應答	IIC_Write_Byte(0x00);IIC_Slave_ACK_NACK();//等待從機應答		IIC_Stop();
}
/*AHT20測量指令
*/
void AHT20_Measure(void)
{IIC_Start();IIC_Write_Byte(0x70);//AHT20從機地址IIC_Slave_ACK_NACK();//等待從機應答IIC_Write_Byte(0xAC);IIC_Slave_ACK_NACK();//等待從機應答	IIC_Write_Byte(0x33);IIC_Slave_ACK_NACK();//等待從機應答	IIC_Write_Byte(0x00);IIC_Slave_ACK_NACK();//等待從機應答	IIC_Stop();
}
/*AHT20濕度數據的拼接函數參數1:*hum_array,拼接后存儲的濕度數據參數2:data,待拼接的濕度數據
*/
void AHT20_Hum_Add(int *hum_array,unsigned char data)
{for(int i=0;i<8;i++){*hum_array=*hum_array<<1;if(data&0x80){*hum_array+=1;}data=data<<1;}
}
/*AHT20溫度數據的拼接函數參數1:*temp_array,拼接后存儲的溫度數據參數2:data,待拼接的溫度數據
*/
void AHT20_Temp_Add(int *temp_array,unsigned char data)
{for(int i=0;i<8;i++){*temp_array=*temp_array<<1;if(data&0x80){*temp_array+=1;}data=data<<1;}
}
/*AHT20溫度和濕度拆分函數參數1:*hum_array,拆分后存儲的濕度數據參數2:*temp_array,拆分后存儲的溫度數據參數3:data,待拆分的數據
*/
void AHT20_Hum_Temp_Split(int *hum_array,int *temp_array,unsigned char data)
{for(int i=0;i<8;i++){if(i<=3){//存儲在濕度*hum_array=*hum_array<<1;if(data&0x80){*hum_array+=1;}data=data<<1;}else{//存儲在溫度*temp_array=*temp_array<<1;if(data&0x80){*temp_array+=1;}data=data<<1;}}
}
/*讀取AHT20溫度和濕度數據
*/
struct AHT20_MSG * AHT20_Read_Temp_Hum(void)
{struct AHT20_MSG *AHT20_P=(struct AHT20_MSG *)malloc(sizeof(struct AHT20_MSG));if(!AHT20_P) //空間分配失敗{return NULL;}AHT20_P->status=0;AHT20_P->temp=0;AHT20_P->hum=0;AHT20_P->crc=0;AHT20_Reset();//重置AHT20HAL_Delay(10);AHT20_Init();//初始化AHT20HAL_Delay(10);AHT20_Measure();//發送AHT20測量指令HAL_Delay(80);//讀取AHT20數據IIC_Start();IIC_Write_Byte(0x71);//AHT20從機地址IIC_Slave_ACK_NACK();//等待從機應答unsigned data=IIC_Read_Byte();//讀取1byte數據---狀態數據AHT20_P->status=data;IIC_Master_ACK();data=IIC_Read_Byte();//讀取1byte數據---相對濕度的高8位數據AHT20_Hum_Add(&AHT20_P->hum,data);//將讀取出來的8位濕度數存儲在濕度中IIC_Master_ACK();data=IIC_Read_Byte();//讀取1byte數據---相對濕度的中8位數據AHT20_Hum_Add(&AHT20_P->hum,data);//將讀取出來的8位濕度數存儲在濕度中IIC_Master_ACK();data=IIC_Read_Byte();//讀取1byte數據---包含了濕度的低4位數據和溫度的高4位數據AHT20_Hum_Temp_Split(&AHT20_P->hum,&AHT20_P->temp,data);IIC_Master_ACK();data=IIC_Read_Byte();//讀取1byte數據---相對溫度的中8位數據AHT20_Temp_Add(&AHT20_P->temp,data);IIC_Master_ACK();data=IIC_Read_Byte();//讀取1byte數據---相對溫度的中8位數據AHT20_Temp_Add(&AHT20_P->temp,data);IIC_Master_ACK();//讀取的是CRC(作者暫未用到)data=IIC_Read_Byte();//讀取1byte數據---CRC校驗數據AHT20_P->crc=data;IIC_Master_NACK();IIC_Stop();return AHT20_P;
}
/*顯示AHT20讀取到的溫度和濕度數據參數:AHT20_P,待顯示的溫度和濕度數據結構體指針
*/
void AHT20_Display_Hum_Temp(struct AHT20_MSG *AHT20_P)
{if((AHT20_P->status&0x68)==0x08){//打印和顯示printf("溫度數據:%0.2f ℃\r\n",(AHT20_P->temp/pow(2,20))*200-50);printf("濕度數據:%0.2f%%\r\n",(AHT20_P->hum/pow(2,20))*100);}free(AHT20_P);HAL_Delay(1000);
}

4.3、main.c


/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************** This notice applies to any and all portions of this file* that are not between comment pairs USER CODE BEGIN and* USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools* are owned by their respective copyright owners.** COPYRIGHT(c) 2025 STMicroelectronics** Redistribution and use in source and binary forms, with or without modification,* are permitted provided that the following conditions are met:*   1. Redistributions of source code must retain the above copyright notice,*      this list of conditions and the following disclaimer.*   2. Redistributions in binary form must reproduce the above copyright notice,*      this list of conditions and the following disclaimer in the documentation*      and/or other materials provided with the distribution.*   3. Neither the name of STMicroelectronics nor the names of its contributors*      may be used to endorse or promote products derived from this software*      without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"/* USER CODE BEGIN Includes */
#include "AHT20.h"
/* USER CODE END Includes *//* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
int fputc(int c, FILE*f)
{HAL_UART_Transmit(&huart1, (uint8_t*)&c,1,2);return c;
}
/* USER CODE END PFP *//* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.** @retval None*/
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();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){AHT20_Display_Hum_Temp(AHT20_Read_Temp_Hum());/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct;RCC_ClkInitTypeDef RCC_ClkInitStruct;/**Configure the main internal regulator output voltage */__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/**Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = 16;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}/**Configure the Systick interrupt time */HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);/**Configure the Systick */HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);/* SysTick_IRQn interrupt configuration */HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}/* USART1 init function */
static void MX_USART1_UART_Init(void)
{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(__FILE__, __LINE__);}}/** Configure pins as * Analog * Input * Output* EVENT_OUT* EXTI
*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;/* GPIO Ports Clock Enable */__HAL_RCC_GPIOF_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOF, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);/*Configure GPIO pins : PF0 PF1 */GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @param  file: The file name as string.* @param  line: The line in file as a number.* @retval None*/
void _Error_Handler(char *file, int line)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */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,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//*** @}*//*** @}*//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

5、STM32F407ZET6測量AHT20溫濕度效果圖

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910093.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910093.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910093.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

很好,搞搞期末

我要開始啦&#xff01;bulabulabulabulabula. 例題 物理地址DS*16有效地址 1.直接尋址 2.直接尋址&#xff08;允許符號代替數值&#xff0c;變量存的地址&#xff09; 3.基址尋址&#xff08;16位&#xff1a;用寄存器SI、DI、BX、BP存的有效地址&#xff09; 下面是寄存器…

機器人如何實現智能化的自主定位與導航?

機器人實現智能化自主定位與導航&#xff0c;需融合多傳感器數據、高效算法及硬件支撐&#xff0c;以下從技術框架、核心技術、典型應用場景等方面詳細解析&#xff1a; 一、技術框架&#xff1a;定位與導航的核心環節 機器人自主定位導航通常包含三個關鍵步驟&#xff0c;形…

AI醫療行業全景圖

AI醫療是以互聯網為依托&#xff0c;通過基礎設施的搭建及數據的收集&#xff0c;將人工智能技術及大數據服務應用于醫療行業中&#xff0c;提升醫療行業的診斷效率及服務質量&#xff0c;更好的解決醫療資源短缺、人口老齡化的問題AI在醫療領域應用廣泛&#xff0c;覆蓋醫療服…

Meta-KDD2025-RPG-token級別并行生成式提高效率!

文章目錄 1. 背景2. 方法2.1 長語義id2.1.1 獲取 item embedding2.1.2 item embedding 離散化 2.2 并行生成語義 id2.2.1 訓練&#xff08;item串行&#xff0c;token并行&#xff09;2.2.2 高效 logit 打分暴力枚舉式打分&#xff1a;高效實現&#xff1a;復雜度分析&#xff…

快速搭建MySQL8.0本地數據庫,連接idea

1.打開終端&#xff0c;按順序輸入命令&#xff0c;在root用戶下&#xff0c;創建用戶和數據庫 1.進入數據庫 mysql -u root -p 2.創建專用數據庫 create database 數據庫名 character set utf8mb4 3.使用數據庫 use 數據庫名 4.設置此數據庫用戶 create user "用戶名&q…

Docker 常用運維命令

Docker 提供了一系列命令來幫助開發者和運維人員管理容器、鏡像以及其他 Docker 對象。以下是一些常用的 Docker 運維命令&#xff0c;這些命令可以幫助你更高效地進行日常操作&#xff1a; 容器相關命令 啟動容器&#xff1a; docker start <container_id_or_name>停止…

linux下MQTT訂閱發布驗證-mosquitto安裝測試流程

本文詳細介紹了&#xff0c;如何在linux環境搭建一個MQTT server, 并同時安裝 了客戶端 &#xff0c;進行了mqtt消息發布、訂閱驗證。 mosquitto 服務端安裝(ubuntu) #添加源 sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppasudo apt update # install mosquitto su…

Source Insight 的簡單介紹

對 Source Insight 進行一次全面深入的介紹。這款軟件在特定開發者群體中&#xff08;尤其是嵌入式、驅動、系統級編程領域&#xff09;享有極高的聲譽&#xff0c;被譽為“源碼閱讀和分析的神器”。 一、 起源與歷史 誕生背景 (1990年代中后期)&#xff1a; 在1990年代中后期…

Linux 系統中,查詢 JDK 的安裝目錄

在 Linux 系統中&#xff0c;查詢 JDK 的安裝目錄可以通過以下幾種常用方法&#xff1a; 方法 1&#xff1a;通過 update-alternatives 查詢&#xff08;推薦&#xff09; 適用于通過包管理器&#xff08;如 apt/yum&#xff09;安裝的 JDK&#xff1a; sudo update-alternat…

簡單工廠、工廠、抽象工廠模式

簡單工廠、工廠、抽象工廠模式 1. **簡單工廠模式&#xff08;Simple Factory&#xff09;**2. **工廠方法模式&#xff08;Factory Method&#xff09;**3. **抽象工廠模式&#xff08;Abstract Factory&#xff09;**對比總結 以下是三種工廠模式在C#中的實現與對比分析&…

如何在Redis中實現緩存功能

Redis 是一種高性能的鍵值存儲系統&#xff0c;廣泛用于實現緩存功能。它通過將數據存儲在內存中&#xff0c;能夠快速讀寫數據&#xff0c;從而顯著提高應用程序的性能。在Redis中實現緩存功能需要結合數據讀寫策略、失效機制及性能優化方案。 一、Redis作為緩存的核心優勢 …

Kafka消費者客戶端源碼深度解析:從架構到核心流程

在Kafka生態系統中&#xff0c;消費者客戶端作為數據消費的入口&#xff0c;其設計與實現直接影響數據處理的效率和可靠性。本文將深入Kafka消費者客戶端源碼&#xff0c;通過核心組件解析、流程拆解與源碼分析&#xff0c;揭示其高性能消費背后的技術奧秘&#xff0c;并輔以架…

從0開始學習R語言--Day26--因果推斷

很多時候我們在探討數據的相關性問題時&#xff0c;很容易會忽略到底是數據本身的特點還是真的是因為特征的區分導致的不同&#xff0c;從而誤以為是特征起的效果比較大。 這就好比測試一款新藥是否真的能治病&#xff0c;假如吃藥的患者康復的更快&#xff0c;那到底是因為藥…

Python 中布爾值的使用:掌握邏輯判斷的核心

在 Python 中&#xff0c;布爾值&#xff08;bool&#xff09;是進行邏輯判斷的基礎。布爾值只有兩個可能的值&#xff1a;True 和 False。通過布爾值&#xff0c;你可以實現條件判斷、循環控制以及其他邏輯操作。今天&#xff0c;就讓我們一起深入探討如何在 Python 中使用布爾…

IDEA 中 Tomcat 部署 Java Web 項目(Maven 多模塊 非 Maven 通用版)(linux+windows)

引言 Java Web 開發中&#xff0c;Tomcat 是最常用的 Servlet 容器&#xff0c;而項目類型通常分為 Maven 管理&#xff08;依賴自動處理、多模塊聚合&#xff09; 和 非 Maven 純手工管理&#xff08;手動引入 jar 包、配置項目結構&#xff09;。本文覆蓋 兩種項目類型 的 T…

使用 React Native Web 實現三端統一開發

使用 React Native Web 實現三端統一開發 關鍵點 React Native Web 簡介&#xff1a;React Native Web 是一個允許開發者使用 React Native 組件和 API 構建 Web 應用的庫&#xff0c;支持在 iOS、Android 和 Web 上使用同一套代碼。架構&#xff1a;通過 React DOM 渲染 Rea…

分享一個git上基于std::array實現的循環隊列(Cycle Queue)模板類庫

為充分利用向量空間,克服“假溢出”現象的方法是:將向量空間想象為一個首尾相接的圓環,并稱這種向量為循環向量。存儲在其中的隊列稱為循環隊列(Circular Queue)。循環隊列是把順序隊列首尾相連,把存儲隊列元素的表從邏輯上看成一個環,成為循環隊列。 網上有很多關于循…

三維視頻融合平臺:如何構建動態感知的數字空間

分享大綱&#xff1a; 你的三維平臺為何不能承載動態視頻捷碼打造三維視頻融合平臺的三步法則為何選擇捷碼 在智慧城市建設過程中&#xff0c;將實時視頻與三維空間結合&#xff0c;已經成為一種主流趨勢。傳統視頻監控模式&#xff0c;經常面臨視頻分散、操作復雜等問題。然而…

【AI Study】第五天,Matplotlib(5)- 顏色映射

文章概要 本文詳細介紹 Matplotlib 的顏色映射功能&#xff0c;包括&#xff1a; 顏色映射類型顏色映射設置數據標準化顏色條 顏色映射類型 pcolormesh import matplotlib.pyplot as plt import numpy as np# 創建網格數據 x np.linspace(-3, 3, 100) y np.linspace(-3,…

DB2中合理使用INCLUDE關鍵字創建索引

DB2中合理使用 INCLUDE 關鍵字創建索引 1. 為何還需要 INCLUDE&#xff1f;——從索引的兩大痛點說起 查詢想“只讀索引不回表”&#xff0c;卻又不想把列都做鍵 → 聯合索引空間膨脹&#xff0c;更新放大。唯一索引定位快&#xff0c;但只能返回鍵列數據 → 仍需 I/O 跳回數據…