stm32串口数据接收hal
时间: 2025-03-16 15:00:35 浏览: 9
STM32 HAL库实现串口数据接收
使用HAL库配置串口接收功能
STM32微控制器可以通过其硬件抽象层(HAL)库来简化外设驱动程序的开发过程。对于串口通信而言,HAL库提供了丰富的API函数用于初始化、发送和接收数据[^1]。
为了实现串口的数据接收,通常有以下几种方法:轮询模式、中断模式以及DMA模式。其中,中断模式适合实时性较高的场景;而DMA模式则适用于大量数据传输的情况[^2]。
中断模式下的串口接收示例代码
以下是基于中断模式的一个典型实现:
#include "stm32f1xx_hal.h"
#define BUFF_SIZE 128 // 接收缓冲区大小
uint8_t rx_buffer[BUFF_SIZE]; // 定义接收缓冲区
// 初始化UART
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600; // 波特率设置为9600bps
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 数据位长度为8位
huart1.Init.StopBits = UART_STOPBITS_1; // 停止位为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(); // 错误处理函数
}
}
// 配置串口中断
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Enable NVIC for USART1_IRQn */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
// 中断服务函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1); // 调用HAL库中的通用中断处理函数
}
// 用户自定义回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1){
// 当接收到数据时触发此回调函数
// 处理rx_buffer中的数据...
// 继续下一次接收操作
HAL_UART_Receive_IT(&huart1, (uint8_t *)rx_buffer, sizeof(rx_buffer));
}
}
上述代码展示了如何利用中断机制完成串口数据的异步接收。MX_USART1_UART_Init()
函数负责初始化串口参数,包括波特率、字长等。而在 HAL_UART_MspInit()
中,则完成了与串口相关的GPIO引脚配置,并启用了相应的NVIC中断向量。
当发生串口中断事件时,会调用到 USART1_IRQHandler()
,该函数内部又进一步调用了 HAL 提供的标准中断处理器 HAL_UART_IRQHandler()
。每当一帧完整的数据被成功接收完毕之后,就会执行用户注册好的回调函数 HAL_UART_RxCpltCallback()
来通知应用程序已准备好新的数据包待处理。
DMA模式下的串口接收示例代码
如果希望采用更高效的DMA方式进行不定长数据接收,可以参考如下片段:
// 启动DMA接收
if(HAL_UART_Receive_DMA(&huart1, (uint8_t*)rx_buffer, BUFF_SIZE)!= HAL_OK){
Error_Handler(); // 如果启动失败进入错误处理流程
}
// 在空闲中断中停止当前DMA通道并保存有效数据数量
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance==USART1){
// 记录实际接收到的有效字节数Size
// 可在此处加入对接收到的数据进行解析或其他逻辑运算的操作
// 再次重新启用DMA接收下一组数据
HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buffer,BUFF_SIZE);
}
}
这里通过调用 HAL_UART_Receive_DMA()
方法指定目标存储区域地址及其容量上限值作为输入参数从而激活DMA引擎开始工作直到遇到特定条件才会终止比如检测到了线路空闲信号等等情况下来源文件里预定义好了相应行为动作即调用 HAL_UARTEx_RxEventCallback()
进行后续步骤安排。
注意事项
- 确保正确设置了系统的时钟树以便满足所选通讯速率需求。
- 对于不同型号芯片可能存在的差异部分需参照官方资料手册调整具体寄存器数值或者结构体成员变量赋初值等内容。
- 编程期间务必留意资源冲突问题例如两个以上任务试图同时访问同一个共享对象可能导致不可预期后果因此建议合理运用互斥锁之类同步工具加以保护措施防止此类现象的发生。
相关推荐


















