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
未完