一、IIC(I2C) 线的作用

               UART总线
PC端(CPU)    <---------->    开发板(STM32U575RIT6)
                            IIC总线
主控芯片(STM32U575RIT6)    <--------->    传感器驱动芯片(SHT20/SI7006空气温湿度传感器)

二、I2C 总线的概念

图 1 I2C 总线示意图
图 2 多主机多从机模式示意图

        I2C 总线也称为 IIC 总线,中文名:集成电路总线

        I2C 总线由飞利浦公司设计,是 串行、同步、半双工总线

        I2C 总线硬件连接为:2 根线I2C_SCL 时钟线I2C_SDA 数据线,都为双向,如图 1 所示,SCL 时钟线和 SDA 数据线都会 外接一个上拉电阻

        I2C 总线的通信速率:

                低速:100 kbps       

                中速:400 kbps       

                高速:3.4 Mbps

        I2C 总线的应用场景:传感器、OLED 屏……

        I2C 总线支持 主从机模式 (Master / Slaver),支持多主机多从机的模式,一般使用单主机多从机

                发送器:用于发送数据的设备

                接收器:用于接收数据的设备

                主机:主动发起数据通信 或者 主动结束数据通信的设备

                从机:被动发起数据通信 或者 被动结束数据通信的设备

        每个挂载在 I2C 总线上的设备,都有一个自己唯一的 7 位设备地址7 位从机地址


三、I2C 总线的硬件连接

3.1 硬件连接

图 3 I2C 总线硬件连接示意图

I2C 总线有 2 根线   --->   I2C_SCL 时钟线I2C_SDA 数据线

  1. SCL 时钟线:用于将挂载在 I2C 总线上的设备的时钟进行同步
  2. SDA 数据线:用于挂载在 I2C 总线上的设备进行数据传输

I2C 总线的 SCL 时钟线和 SDA 数据线都外接一个上拉电阻

作用:

  1. I2C 总线在没用进行数据通信,即 I2C 总线处于空闲的状态时,SCL 时钟线和 SDA 数据线处于高电平状态
  2. 外接上拉电阻后,可以一定程度上稳定电路减少 I2C 总线传输数据的损耗

3.2 单主机多从机的模式

主机:STM32U575RIT6


从机 1:E2PROM        ---        0x10

从机 2:A / D 模数转换器        ---        0x20

从机 3:时钟日历        ---        0x30

从机 4:空气温湿度传感器SHT20        ---        0x40

1)问题

        主机想要获取从机 4 的数据(主机和从机 4 进行数据通信),由于存在 4 个从机设备,主机如何找到从机 4 空气温湿度传感器?

2)解释

  1. 每个挂载在 I2C 总线上的设备,都有自己的一个唯一的 7 位设备地址(7 位从机地址)
  2. 主机会向挂载在 I2C 总线上的每个从机设备发送想要通信的从机的设备地址
  3. 每个从机都获取到主机发送的从机地址,和自己的从机地址作比较,如果相等就进行通信,不相等就不通信
  4. 7 位从机地址不是理论上的内存地址(不占用内存空间),只是一个标识符(数字、ID 号)

3.3 多主机多从机的模式

主机 1:STM32U575RIT6        ---        0x01

主机 2:STM32MP157AAA        ---        0x02


从机 1:E2PROM        ---        0x10

从机 2:A/D模数转换器        ---        0x20

从机 3:时钟日历        ---        0x30

从机 4:空气温湿度传感器SHT20        ---        0x40

1)举例

        直接编程控制 U5,U5 先给 MP157A 发送数据(命令:让 MP157A 回复数据),当 MP157A 收到命令后,又会回复数据给 U5

主机:STM32U575RIT6

从机:STM32MP157AAA

  1. STM32U575RIT6 -> STM32MP157AAA (U5 是发送器,MP157A 是接收器)
  2. STM32MP157AAA -> STM32U575RIT6 (MP157A 是发送器,U5 是接收器)

主机和从机都可以担任发送器和接收器的角色,只是区别在于一个是主动一个是被动

3.3 空气温湿度实验

直接编程控制 -> STM32U575RIT6

获取空气温湿度数据 -> SHT20 / SI7006

                通过IIC总线发送命令
STM32U575RIT6 ---------------------> SHT20/SI7006
                通过IIC总线发送空气温湿度数值                    UART总线
SHT20/SI7006  ------------------------------> STM32U575RIT6 -------------> PC端的串口工具

四、I2C 总线的时序图

时序图:随着时钟线的变化顺序,数据线也产生对应变化 / 操作的图

4.1 起时信号与终止信号的时序图

图 4 起时信号与终止信号时序图

如图所示:

起始信号(S):当 SCL 时钟信号处于高电平期间,SDA 数据线从高电平变为低电平 -> 产生一个下降沿信号时,标志着一次 IIC 总线通信的开始;

终止信号(P):当 SCL 时钟信号处于高电平期间,SDA 数据线从低电平变为高电平 -> 产生一个上升沿信号时,标志着一次 IIC 总线通信的结束。

注意:

  1. 当产生一个起时信号后,IIC 总线处于占用状态,此时,IIC 总线的 SLC 时钟线处于低电平状态
  2. 当产生一个终止信号后,IIC 总线处于空闲状态,此时,IIC 总线的 SLC 时钟线处于高电平状态
  3. 起时信号和终止信号只能由主机产生

4.2 数据传输信号的时序图

图 5 数据传输信号时序图

如上图所示,为数据传输信号时序图:

  1. 数据接收信号:当 SCL 时钟线处于高电平状态时,SDA 数据线上的数据要求稳定,不允许发生变化,此时接收器从 IIC 总线上读取数据;
  2. 数据发送信号:当 SCL 时钟线处于低电平状态时,SDA 数据线上的数据允许发生变化,此时发送器可以向 IIC 总线上发送数据。

IIC 总线传输数据时,数据的最小单位为字节8 位

时钟周期:一个高电平 + 一个低电平组成的时钟信号的时间

想要完成一次最小单位的数据收发需要 8 个时钟周期

4.3 应答信号 / 非应答信号的时序图

图 6 应答信号时序图

如图所示:

        主机每 1 个时钟周期向 I2C 总线上传输 1 bit 的数据,I2C 总线的最小传输单位为字节(8 bit)

        I2C 总线每完成一次最小单位的数据传输(需要 8 个时钟周期),接收器在第 9 个时钟周期需要向发送器回复一个应答 / 非应答信号

  • 应答信号(1 bit)0
  • 非应答信号(1 bit)1

存在 2 种情况:

1. 主机发,从机收
主机:发送器

        从机:接收器

当主机发送完 1 个字节(8 位)的数据后:

        主机:接收器

        从机:发送器

        从机回复应答信号


2. 主机收,从机发

        主机:接收器

        从机:发送器

当从机发送完 1 个字节(8 位)的数据后:
主机:发送器

        从机:接收器

        主机回复应答信号

4.4 寻址信号(一种特殊的数据传输信号

图 7 寻址信号数据位

寻址信号:主机发送的用于寻找需要通信的从机的地址信号

  1. 寻址信号一定由主机发送,必须跟在起时信号后
  2. 从机地址是 7 位,而 I2C 总线最小传输单位为 8 位,需要添加 1 位,才可以发送
  3. 添加的 1 位是 R / W 位:

                W(0):写标志位,代表主机向 IIC 总线上写入数据

                R(1):读标志位,代表主机要从 IIC 总线上读取数据

主机想要找到0x40的从机 -----> 主机想要IIC总线上的SDA数据线发送0x40 -------> 寻址信号最低位需要为W(0)

从机的设备地址为:0x40

        主机发,从机收:寻址信号 -> (0x40 << 1) | 0

        主机收,从机发:寻址信号 -> (0x40 << 1) | 1

五、IIC 总线的协议格式

IIC 总线协议的组成:起时信号、终止信号、寻址信号、数据传输信号、应答 / 非应答信号

5.1 主机向从机发送 1 个字节数据的协议格式

图 8 主机向从机发送 1 个字节数据协议格式

        首先主机发送一个起时信号后,紧接着发送一个 7 位从机地址和 1 个 W(0)组合的 8 位寻址信号,收到 1 bit 对应从机的 ACK 信号,再接着发送一个 8 位的寄存器地址寻问从机是否有对应地址寄存器,若有,则从机发送一个 ACK 信号,接着主机再发送 8 位的实际数据,从机接收到后发送一个 ACK 信号,接着由主机发送一个上升沿终止信号结束此次 I2C 通信。

5.2 主机向从机发送多个字节数据的协议格式

1)寄存器地址连续

图 9 主机向从机发送多个字节数据协议格式(寄存器地址连续)

        与发送单个数据不同的是,在发送完第 1 个 8 位实际数据后,在收到从机的 ACK 后,主机会继续发送下一个 8 位数据,数据自动存入 REG + 1 的寄存器中,数据全部发送完毕后,主机发送一个上升沿终止信号结束此次 I2C 通信。

2)寄存器地址不连续

图 10 主机向从机发送多个字节数据协议格式(寄存器地址不连续)

        当寄存器地址不连续时,由于要存的新的 8 位寄存器地址是特殊的数据,跟在寻址信号后,而寻址信号必须在起时信号后,所以要存入新寄存器的话,必须先发送终止信号,随后重新发送起始信号、寻址信号以及新的 8 位寄存器地址。

5.3 主机从从机读取一个字节数据的协议格式

图 11 主机从从机读取一个字节数据协议格式

主机从从机读取数据时,为什么要读写转换,即先写后读,不能直接读?

  1. 首先主机要先找到从机,向每个从机发送 7 位从机地址,既是发送,就是要先写;
  2. 主机找到从机后,要询问从机是否有可用的寄存器地址空间,把 8 位寄存器地址发送给从机,从机判断;
  3. 只有找到了从机,并且确认寄存器地址存在,才开始从从机中读取数据。

使用 IIC 总线读取数据时,为什么主机结束通信前要给从机发送一个 NACK 非应答信号?

        这是由主机和从机的特性决定

  • 主机主动发起数据通信或者主动结束数据通信的设备,具备主动性
  • 从机被动接收数据通信或者被动结束数据通信的设备,具备被动性

        如果从机开始给主机发送数据,不让从机停止发送,他会一直发送,就需要主机给从机发送一个NACK信号,告诉从机结束发送。

5.4 主机从从机读取多个字节数据的协议格式

图 12 主机从从机读取多个字节数据协议格式

六、分析电路图

6.1 查找引脚

1)找到空气温湿度传感器 SHT20 / SI7006 芯片进行 IIC 总线通信的引脚?

图 13

I2C1_SCL        --->        PB6

I2C1_SDA        --->        PB7


七、分析芯片手册(SHT20 / SI7006)

7.1 查找手册的目的

1)查找信息

  1. SHT20 / SI7006 从机的从机地址
  2. 存储空气温度数据和空气湿度数值的寄存器地址
  3. 知道当前空气温湿度传感器支持的检测精度
  4. 将空气温湿度模拟量和空气温湿度数字量转换的公式
  5. 空气温湿度传感器的工作环境范围

7.2 框图分析

1)总体框图

图 14 总体框图

2)使用 IIC 外设控制器框图

图 15 使用 IIC 外设控制器框图

3)GPIO引脚直接模拟IIC总线协议的时序

图 16 GPIO 引脚直接模拟 IIC 总线协议时序框图

7.3 手册分析

图 17 SHT20 温湿度传感器特性
图 18 SHT20 温湿度传感器误差
图 19 SHT20 温湿度传感器电器规格

1)7 位设备地址和读写标志位

图 20 设备地址
图 21 SHT20 温湿度传感器协议格式

2)8 位寄存器地址

图 22 SHT20 温湿度传感器 8 位寄存器地址

hold master:保持主机占用模式(单主机模式)
no hold master:不保持主机占用模式(多主机模式)

存储空气温度数字量的寄存器        ---        0xE3
存储空气湿度数字量的寄存器        ---        0xE5

3)测量精度设置

图 23 SHT20 温湿度传感器测量精度的设置

向用户寄存器中的第 7 和第 0 位写入 0b00
指定空气湿度的测量结果为 12 位的数据
指定空气温度的测量结果为 14 位的数据

4)温湿度测量并转化需要的时间

图 24 SHT20 温湿度传感器测量时间

5)温湿度数字量和模拟量转换公式

图 25 湿度数字量和模拟量转换公式

图 26 温度数字量和模拟量转换公式


八、CubeMX 工程配置

图 27 选择芯片 STMU575RIT6
打开 STM32CubeMX,点击创建新工程,如上图所示,找到 STM32U575RIT6 芯片,双击或者点击右上角的按钮开始工程。
图 28 配置引脚 PB6、PB7
单击 PB6 和 PB7 引脚,分别配置为 I2C1_SCL 和 I2C1_SDA 模式,左侧找到 I2C,选择为 I2C ,下方设置表示:标准速率模式100 kHz 速率使用 7 位从机地址
图 29 配置引脚 PA9、PA10
为了将获取到的温湿度数据显示出来,需要同过 UART 总线显示到串口终端上,需要配置 PA9 和 PA10 分别为 USART1_TX 和 USART1_RX 模式,左侧找到 USART1,选择模式为 Asynchronous,可选择设置速率为 9600 Bit / s 以及数据位个数和是否有校验位,一般设置为 8N1 格式。
图 30 打开串行烧录模式

        左侧找到 DEBUG,选择 Serial Wire,即打开串行烧录模式。

        点击,设置时钟频率:

图 31 设置工程路径

        如图所示设置工程名字和选择编辑器 MDK-ARM。

图 32 生成工程代码
如图所示选择和勾选相关选项后,点击  直接生成代码。

九、Keil 工程

9.1 API 接口

图 33 函数接口

1)主机发送函数 HAL_I2C_Master_Transmit

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size, uint32_t Timeout)
功能:

        HAL 库提供的用于主机向 I2C 总线上发送数据的函数(主机向从机发送数据)

参数:

        hi2c:i2c1 外设控制器的句柄对象

        DevAddress写权限寻址信号7 位从机地址 + W

        pData:要发送的数据

        Size:要发送的数据的大小,单位位字节

        Timeout:超时检测时间,当前函数最大支持的阻塞时间,单位为 ms

返回值:

        执行成功,返回 HAL_OK ( 0 )

        执行失败,返回错误码

        返回值 HAL_StatusTypeDef 枚举类型如下:

typedef enum
{HAL_OK       = 0x00,HAL_ERROR    = 0x01,HAL_BUSY     = 0x02,HAL_TIMEOUT  = 0x03
} HAL_StatusTypeDef;

2)主机接收函数 HAL_I2C_Master_Receive

HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,uint32_t Timeout)
功能:

        HAL 提供的用于主机从 I2C 总线上读取数据的函数(主机从从机读取数据)

参数:

        hi2c:i2c 外设控制器的句柄对象

        DevAddress读权限寻址信号7 位从机地址 + R

        pData:要读取的数据(被读取的数据所在的存储器地址)

        Size:要读取的数据大小(被读取的数据所在寄存器的容器大小)

        Timeout:超时检测时间,当前函数执行的最大阻塞时间,单位是 ms

返回值:

        执行成功,返回 HAL_OK ( 0 )

        执行失败,返回错误码

9.2 添加 sht20.c 和 sht20.h 文件

        我们需要去封装函数去完成 找到从机温湿度传感器并从中获取温湿度数据 和 将温湿度数据的模拟量转换为模拟量并在串口终端显示

        在当前工程目录下创建一个新的文件夹,比如 BSP_SHT20,便于后续管理自己的代码文件,在 BSP_SHT20 目录下创建 sht20.c 和 sht.h 文件。

图 34

        点击如图所示位置,打开如下添加新文件夹到工程的窗口:

图 35 添加文件夹

        按如图方式点击并输入和我们所创文件夹名字相同的名字,点击 Add Files 将 .c 和 .h 文件加入进来。

图 36

        在 sht.c 文件中包含 sht.h 文件,并编译一遍,就可以在左侧展开 sht.c 看到 sht.h 文件打开并编辑。

        注意:

        如果main.c 文件包含 sht.h 文件时找不到文件,需要添加设置编译器包含路径:

        点击,选择 C / C++,按下图设置

图 37 设置编译器包含路径

9.3 代码

1)sht20.h

#ifndef __SHT20_H
#define __SHT20_H#include "stdint.h"
#include "i2c.h"//STH20从机7位地址
#define SHT20_ADDRESS 0x40
//写权限寻址信号
#define SHT20_ADDRESS_W	((SHT20_ADDRESS << 1)|0)
//读权限寻址信号
#define SHT20_ADDRESS_R	((SHT20_ADDRESS << 1)|1)//温度数据寄存器地址
#define TEMP_CMD 0xE3//湿度数据寄存器地址
#define HUM_CMD 0xE5  //温湿度数据获取函数
uint32_t SHT20_Get_Data(uint8_t register_t);//串口显示函数
void SHT20_Digital_to_Analog(uint16_t temp_digital,uint16_t hum_digital);#endif

2)sht20.c

#include "sht20.h"
#include "main.h"/**函数:SHT20_Get_Data*功能:获取SHT20空气温湿度传感器采集到的数据(数字量)*参数:空气温度数据寄存器的地址/空气湿度数据寄存器的地址*返回值:获取到的SHT20传感器的值*/
uint32_t SHT20_Get_Data(uint8_t register_t)
{uint16_t data;uint8_t buf[2]={0x00, 0x00};//主机发送写权限寻址信号+8位寄存器地址HAL_I2C_Master_Transmit(&hi2c1, SHT20_ADDRESS_W, &register_t, 1, 5);//主机发送写权限寻址信号和8位寄存器地址后,开始读取数据HAL_I2C_Master_Receive(&hi2c1, SHT20_ADDRESS_R, buf, 2, 100);data=(buf[0]<<8 | buf[1]);return data;
}/** 函数:SHT20_Digiatl_To_Analog* 功能:将温湿度数字量转换为模拟量并串口显示* 参数:tem_digital:温度数字量    hum_digital:湿度数字量* 返回值:无*/
void SHT20_Digital_to_Analog(uint16_t temp_digital,uint16_t hum_digital)
{float tem_analog, hum_analog;tem_analog = temp_digital * 175.72 /65536 - 46.85;hum_analog = hum_digital *125 / 65536 - 6;printf("TEM=%.2f, HUM=%.2f",tem_analog,hum_analog);if(tem_analog>=30){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET);}else if(tem_analog<30){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET);}if(hum_analog>=70){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);}else if(hum_analog<70){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);}
}

3)main.h

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.h* @brief          : Header for main.c file.*                   This file contains the common defines of the application.******************************************************************************* @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 __MAIN_H
#define __MAIN_H#ifdef __cplusplus
extern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "stm32u5xx_hal.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET *//* USER CODE END ET *//* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC *//* USER CODE END EC *//* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM *//* USER CODE END EM *//* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);/* USER CODE BEGIN EFP *//* USER CODE END EFP *//* Private defines -----------------------------------------------------------*//* USER CODE BEGIN Private defines *//* USER CODE END Private defines */#ifdef __cplusplus
}
#endif#endif /* __MAIN_H */

4)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 "sht20.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 */
int fputc(int ch, FILE* stream)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 5);return ch;
}
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void SystemPower_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();/* Configure the System Power */SystemPower_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_I2C1_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */uint16_t temp,hum;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){temp=SHT20_Get_Data(TEMP_CMD);hum=SHT20_Get_Data(HUM_CMD);SHT20_Digital_to_Analog(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 = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;RCC_OscInitStruct.MSIState = RCC_MSI_ON;RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4;RCC_OscInitStruct.PLL.PLLM = 3;RCC_OscInitStruct.PLL.PLLN = 10;RCC_OscInitStruct.PLL.PLLP = 2;RCC_OscInitStruct.PLL.PLLQ = 2;RCC_OscInitStruct.PLL.PLLR = 1;RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1;RCC_OscInitStruct.PLL.PLLFRACN = 0;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_CLOCKTYPE_PCLK3;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK){Error_Handler();}
}/*** @brief Power Configuration* @retval None*/
static void SystemPower_Config(void)
{/** Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral*/HAL_PWREx_DisableUCPDDeadBattery();
/* USER CODE BEGIN PWR */
/* USER CODE END PWR */
}/* 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 */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/100316.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/100316.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/100316.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 数据结构源码剖析(SDS、Dict、Skiplist、Quicklist、Ziplist)

Redis 数据结构源码剖析&#xff08;SDS、Dict、Skiplist、Quicklist、Ziplist&#xff09;1. 前言 Redis 的高性能与丰富数据结构密切相关。 核心数据结构包括&#xff1a; SDS&#xff08;Simple Dynamic String&#xff09;&#xff1a;字符串底层实现。Dict&#xff08;哈希…

无人机图传系统的功能解析和技术实现原理

无人机图传系统要将机载摄像头捕捉到的画面以尽可能低的时延、尽可能高的清晰度、稳定可靠地送达地面操作员或指挥中心&#xff0c;进而驱动现场行动。为此&#xff0c;核心功能可以从四个维度来解构&#xff1a;实时性、画质与稳定性、覆盖与冗余、以及安全协同。实时性要求在…

微服务网关的bug

从你提供的Eureka控制台信息来看&#xff0c;SPRINGCLOUD-PRODUCT已成功注册到Eureka&#xff0c;且状态为UP&#xff08;实例地址localhost:springcloud-product:8082&#xff09;&#xff0c;排除了“服务未注册”“实例离线”的基础问题。但仍报“负载均衡无可用服务”&…

LeetCode:2.字母异位词分组

目录 1.字母异位词分组 1.字母异位词分组 对于这道题来说&#xff0c;关键的地方在于字母异位词他们排序后的字符串完全相等&#xff0c;所以我们可以通过哈希表来建设一个字符串和其排序相同的字符串数组的映射关系 class Solution { public:vector<vector<string>…

SwiftData3 一剑封喉:WWDC25 的“数据剑谱”精讲,让 Core Data 老侠原地退休

文章目录每日一句正能量一、开场白&#xff1a;老兵的隐痛二、SwiftData3 新剑谱总览三、亮剑&#xff1a;30 行代码搭一个「跨端秒级同步」的收藏夹1. 铸剑&#xff1a;声明模型2. 开锋&#xff1a;初始化容器3. 出招&#xff1a;SwiftUI7 直接绑四、进阶剑气&#xff1a;Char…

微服务-nacos服务中心

单体与微服务 单体架构&#xff1a;项目所有功能都在一个 war 包 /jar 包里&#xff0c;像商城的订单、库存、会员、支付等服务&#xff0c;都打包在一起&#xff0c;部署在 Tomcat 服务器&#xff0c;数据存在 MySQL。 优点&#xff1a;开发简单&#xff0c;易于理解和维护&am…

嵌入式硬件——IMX6ULL 裸机LED点亮实验

一. 实验准备 基于正点原子 IMX6ULL-Mini 开发板&#xff0c;实现 LED 周期性闪烁功能&#xff0c;需完成环境搭建与硬件原理确认两大核心准备工作。 1.1 开发环境搭建 需在Windows和Ubuntu中安装工具&#xff0c;确保文件传输、交叉编译、代码编辑功能正常。1.1.1 跨系统文件传…

深度学习之PyTorch基本使用(一)

一、PyTorch简介与安装1.核心概念PyTorch 是一款 Python 深度学习框架&#xff0c;其核心是张量&#xff08;Tensor&#xff09; —— 元素为同一种数据类型的多维矩阵&#xff0c;以 “类” 的形式封装&#xff0c;内置了张量运算、处理等方法&#xff0c;是深度学习中数据存储…

SQLAlchemy -> Base.metadata.create_all(engine )详解

目录 一、核心作用 二、是否每次运行项目都会执行&#xff1f; 1. ​​典型场景​​&#xff08;推荐&#xff09; 2. ​​需要避免的情况​​ 三、最佳实践建议 1. ​​生产环境​​ 2. ​​开发/测试环境​​ 四、常见问题解答 Q1: 如果表结构改了&#xff0c;creat…

C++异步任务处理与消息可靠性保障指南:从基础到实战

在当今多核处理器普及的时代&#xff0c;程序性能和响应能力的提升成为开发者面临的核心课题。无论是高频交易系统的毫秒级响应需求、实时游戏引擎的流畅交互体验&#xff0c;还是网络服务器的高并发处理能力&#xff0c;异步编程都已成为突破性能瓶颈的关键技术[1]。作为高性能…

LazyForEach性能优化:解决长列表卡顿问题

本文将深入解析HarmonyOS中LazyForEach的工作原理、性能优势、实战优化技巧及常见问题解决方案&#xff0c;帮助你构建流畅的长列表体验。 1. LazyForEach 核心优势与原理 LazyForEach 是鸿蒙ArkUI框架中为高性能列表渲染设计的核心组件&#xff0c;其核心设计思想基于动态加载…

Spring Boot 全栈优化:服务器、数据、缓存、日志的场景应用!

Spring Boot以其“开箱即用”闻名&#xff0c;但默认配置往往在高并发场景下成为瓶颈&#xff1a;Tomcat线程堵塞、数据库连接耗尽、缓存命中率低下、日志洪水般淹没磁盘。想象一个电商微服务&#xff0c;峰值流量下响应迟钝&#xff0c;用户流失——这不是宿命&#xff0c;而是…

Leetcode sql 50 ~5

select product_idfrom Productswhere low_fats Y and recyclable Y;SQL 规定&#xff1a;null 的比较必须用 is null 或 is not null&#xff0c;不能用普通的等号&#xff08;&#xff09;。# Write your MySQL query statement below select name from Customer where ref…

C#高并发与并行理解处理

目录 1.什么是IO密集型任务/CPU密集型任务 2.高并发概念和技术实现 2.并行&#xff08;Parallelist&#xff09;概念和技术实现 4.核心区别对比 1.什么是IO密集型任务/CPU密集型任务 1.IO密集型任务&#xff1a; 定义&#xff1a;任务核心逻辑不依赖CPU计算&#xff0c;而是…

正点原子STM32F407 U盘升级程序(IAP)OTA Bootloader APP USB升级+FATFS+USB Host

正点原子STM32F407 U盘升级程序&#xff08;IAP&#xff09;OTA Bootloader APP USB升级FATFSUSB HostChapter0 解决STM32 Bootloader跳转APP失败问题问题背景问题描述问题解决原APP跳转的函数为&#xff1a;修改APP程序main入口处Chapter1 MDK如何生成*.bin格式的文件Chapter2…

MySQL 8.0 在 Ubuntu 22.04 中如何将启用方式改为mysql_native_password(密码认证)

MySQL 8.0 在 Ubuntu 22.04 中默认启用了 auth_socket 认证方式(而非密码认证),导致 mysql_secure_installation 跳过了 root 密码设置。这会直接影响后续用 Navicat 连接 MySQL(因为 Navicat 需要密码登录),必须手动调整 root 用户的认证方式并设置密码。 核心问题:au…

七层网络协议-面试

七层网络协议概述七层网络协议&#xff0c;即OSI&#xff08;Open Systems Interconnection&#xff09;模型&#xff0c;是由国际标准化组织&#xff08;ISO&#xff09;提出的网络通信框架。它将网络通信过程划分为七个层次&#xff0c;每一层负责特定的功能&#xff0c;并通…

【Blender】二次元人物制作【二】:五官的制作

一、制作眼睛 选中眼眶内部的一圈线。shiftD复制出来调整成圆形&#xff0c;然后F快捷键填充将眼睛放在眼框内合适的位置&#xff0c;并用i键进行几次内插&#xff0c;做出瞳孔&#xff0c;并且将内部的眼瞳做得稍微向内凹陷一点。二、制作睫毛 选中眼眶上半部分的面&#xff0…

Deepin 25 系统安装 Docker:完整教程 + 常见问题解决

Deepin 25 系统安装 Docker&#xff1a;完整教程 常见问题解决 作为基于 Debian 的 Linux 发行版&#xff0c;Deepin 25 因系统目录&#xff08;如/usr&#xff09;默认只读的特性&#xff0c;安装 Docker 时需特殊处理 GPG 公钥存储路径。本文结合社区实践&#xff0c;整理出…

Redis MySQL小结

问题1&#xff1a;Redis为什么高效&#xff1f;答&#xff1a;基于内存&#xff0c;reactor&#xff0c;value的数据组织&#xff08;五种数据结构&#xff09;&#xff0c;KV的数据组织方式&#xff08;渐进hash&#xff09;问题2&#xff1a;跳表是什么&#xff1f;和红黑树的…