> 技术文档 > STM32HAL库常用函数使用说明_stm32hal库函数中文手册

STM32HAL库常用函数使用说明_stm32hal库函数中文手册


STM32HAL库常用函数使用说明(持续更新)


文章目录

  • STM32HAL库常用函数使用说明(持续更新)
  • 前言
  • 1、GPIO
    • 1.1 GPIO高低电平设置
    • 1.2 读取 GPIO 引脚电平
    • 1.3 反转 GPIO 引脚状态(取反)
    • 1.4 初始化 GPIO 引脚(一般由 CubeMX 自动生成)
    • 1.5 外部中断回调函数
  • 2 USART串口
    • 2.1 阻塞模式
      • 2.1.1 发送数据
      • 2.1.2 接收数据
    • 2.2 非阻塞中断模式
      • 2.2.1 开启中断发送
      • 2.2.2开启中断接收
    • 2.3 DMA 模式
      • 2.3.1 开启DMA发送
      • 2.3.2 开启 DMA 接收
    • 2.4 错误处理
    • 2.5 初始化函数(一般由 CubeMX 生成)
    • 2.6 串口收发示例:回显功能
  • 3 基本定时器
    • 3.1 启动定时器
      • 3.1.1 无中断
      • 3.1.2 启用中断
    • 3.2 停止定时器
      • 3.2.1 无中断
      • 3.2.2 启用中断
    • 3.3 回调函数(中断触发时)
    • 3.4 修改计数器值
    • 3.5 判断是否发生了更新事件
    • 3.6 清除更新中断标志位
    • 3.7 在 STM32 中使用定时器实现 1us / 1ms / 1s 周期事件
      • 原理简述:
      • 以 72MHz 定时器时钟为例

前言

HAL函数示例说明


1、GPIO

GPIO控制函数:

1.1 GPIO高低电平设置

HAL_GPIO_WritePin(GPIOx, GPIO_Pin, PinState);

GPIOx:GPIO 端口(如 GPIOA、GPIOB)。
GPIO_Pin:GPIO 引脚(如 GPIO_PIN_0、GPIO_PIN_1)。
PinState:
GPIO_PIN_SET:设置高电平。
GPIO_PIN_RESET:设置低电平。

1.2 读取 GPIO 引脚电平

GPIO_PinState HAL_GPIO_ReadPin(GPIOx, GPIO_Pin);

返回值:
GPIO_PIN_SET(高电平)
GPIO_PIN_RESET(低电平)
示例

GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);if (pinState == GPIO_PIN_SET) { // PA5 为高电平} else { // PA5 为低电平}

1.3 反转 GPIO 引脚状态(取反)

HAL_GPIO_TogglePin(GPIOx, GPIO_Pin);

示例

HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 反转 PA5 电平

1.4 初始化 GPIO 引脚(一般由 CubeMX 自动生成)

GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能 GPIOA 时钟GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

1.5 外部中断回调函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);

这是一个 弱定义函数(__weak),用户可以在自己的代码中重写它来自定义处理逻辑。

使用示例

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if (GPIO_Pin == GPIO_PIN_13) { // 例如:按键按下,翻转 LED 状态 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); }}

2 USART串口

2.1 阻塞模式

2.1.1 发送数据

阻塞模式下,CPU 会等待数据传输完成后才继续执行下一条指令。适用于简单的通信场景。

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  • huart:串口句柄(例如 &huart1)。
  • pData:要发送的数据缓冲区。
  • Size:发送数据长度。
  • Timeout:超时时间(单位:毫秒)。
    示例
uint8_t msg[] = \"Hello, UART!\";HAL_UART_Transmit(&huart1, msg, sizeof(msg) - 1, HAL_MAX_DELAY);

HAL_MAX_DELAY 让传输等待直到完成,不超时。

2.1.2 接收数据

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

示例

uint8_t rx_data[10];HAL_UART_Receive(&huart1, rx_data, 5, 1000); // 1 秒内接收 5 个字节

如果 超时时间到了但数据还没接收完,函数会返回 HAL_TIMEOUT。

2.2 非阻塞中断模式

非阻塞模式使用 中断 来处理数据,适用于接收不定长数据,CPU 不会等待传输完成,可以执行其他任务。

2.2.1 开启中断发送

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

示例

uint8_t msg[] = \"Hello, IT Mode!\";HAL_UART_Transmit_IT(&huart1, msg, sizeof(msg) - 1);

发送完成后,STM32 自动调用回调函数:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { // 发送完成后执行的操作 }}

2.2.2开启中断接收

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

示例

uint8_t rx_data;HAL_UART_Receive_IT(&huart1, &rx_data, 1);

接收 1 个字节 后,STM32 自动调用回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { HAL_UART_Transmit(&huart1, &rx_data, 1, HAL_MAX_DELAY); // 回显数据 HAL_UART_Receive_IT(&huart1, &rx_data, 1); // 继续接收 }}

注意: 必须在回调函数中重新启动 HAL_UART_Receive_IT(),否则不会继续接收数据。

2.3 DMA 模式

DMA(Direct Memory Access)模式让 MCU 硬件直接搬运数据,不占用 CPU 资源,适用于高速数据传输。

2.3.1 开启DMA发送

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

示例

uint8_t msg[] = \"Hello, DMA!\";HAL_UART_Transmit_DMA(&huart1, msg, sizeof(msg) - 1);

发送完成后,STM32 自动调用回调函数:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { // DMA 发送完成 }}

2.3.2 开启 DMA 接收

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

示例

uint8_t rx_buffer[100];HAL_UART_Receive_DMA(&huart1, rx_buffer, 100);

数据接收完成后,STM32 自动调用回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { // DMA 接收完成 }}

2.4 错误处理

HAL_UART_ErrorCallback()发生错误(如帧错误、过载等)
使用示例

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART2) { // 处理串口错误 }}

2.5 初始化函数(一般由 CubeMX 生成)

HAL_UART_Init(&huart2); // 初始化 USART2

这个函数一般不用手动调用,CubeMX 会生成:

2.6 串口收发示例:回显功能

实现功能:串口助手发送什么,STM32 就返回什么。

#include \"usart.h\"uint8_t g_rx_buffer;void MX_USART1_UART_Init(void){ huart1.Instance = USART1; huart1.Init.BaudRate = 9600; 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(); } // 启动串口接收中断 HAL_UART_Receive_IT(&huart1, &g_rx_buffer, 1);}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ if (huart->Instance == USART1) { HAL_UART_Transmit(&huart1, &g_rx_buffer, 1, HAL_MAX_DELAY); // 直接回显 HAL_UART_Receive_IT(&huart1, &g_rx_buffer, 1); // 继续接收 }}

测试方法:
用串口助手连接 STM32(波特率 9600)
发送 “12345”,MCU 立即回显 “12345”

3 基本定时器

3.1 启动定时器

3.1.1 无中断

HAL_TIM_Base_Start(&htim6);

3.1.2 启用中断

HAL_TIM_Base_Start_IT(&htim6);

注意 使用这个函数前应配置好 NVIC 并开启对应中断

3.2 停止定时器

3.2.1 无中断

HAL_TIM_Base_Stop(&htim6);

3.2.2 启用中断

HAL_TIM_Base_Stop_IT(&htim6);

3.3 回调函数(中断触发时)

定时器计数达到周期触发中断时被调用

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if (htim->Instance == TIM6) { // TIM6 中断触发,执行相关操作 }}

3.4 修改计数器值

__HAL_TIM_SET_COUNTER(&htim6, 0);  // 重置计数器uint32_t count = __HAL_TIM_GET_COUNTER(&htim6); // 读取当前计数

3.5 判断是否发生了更新事件

if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE)) { // 说明定时器更新事件发生了}

3.6 清除更新中断标志位

__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);

说明

  • &htim2 是 TIM_HandleTypeDef 类型的结构体指针。
  • TIM_FLAG_UPDATE 表示“定时器是否产生了更新事件”

3.7 在 STM32 中使用定时器实现 1us / 1ms / 1s 周期事件

  • PSC:预分频器(Prescaler)
  • ARR:自动重装载寄存器(Auto-Reload Register)

原理简述:

定时器的计数频率公式为:

计数频率 = 定时器时钟频率 / (PSC + 1)

当计数器从 0 数到 ARR 时产生一次更新事件:

时间间隔(秒) = (ARR + 1) / 计数频率

频率(Hz)和周期(秒)是互为倒数的关系:

周期(秒) = 1 / 频率(Hz)

例:

频率 = 10kHz = 10,000 Hz周期 = 1 / 10000 = 0.0001= 0.1 毫秒 = 100 微秒// 假设时钟72MHzPSC = 7200 - 1; // 计数频率 = 72MHz / 7200 = 10kHzARR = 10000 - 1; // 每次中断需要计数10000次// 那么中断周期就是:时间 = 10000 * (1 / 10000Hz) = 1

以 72MHz 定时器时钟为例

1us(微秒)一次中断:

PSC = 72 - 1 = 71 // 72MHz / 72 = 1MHz → 每个计数为 1usARR = 1 - 1 = 0 // 每计数 1 次产生中断 → 周期 1us

1ms(毫秒)一次中断:

PSC = 72 - 1 = 71 // 1MHz → 每计数为 1usARR = 1000 - 1 = 999 // 每计数 1000 次 → 1000us = 1ms

1s(秒)一次中断:

PSC = 7200 - 1 = 7199 // 72MHz / 7200 = 10kHz → 每计数为 0.1msARR = 10000 - 1 = 9999 // 10000 次 * 0.1ms = 1s

未完