一、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 跳回数据…