下面为你分享一个基于 STM32 HAL 库的串口通信库封装实现。这个库提供了简洁的 API 接口,支持多串口管理、中断接收、DMA 发送等功能,适用于 STM32 全系列微控制器。
库设计思路
这个串口库采用面向对象的设计思想,将每个串口抽象为一个对象,提供初始化、配置、读写等接口。主要包含以下模块:
- 串口设备管理
- 同步 / 异步数据收发
- 中断 / DMA 支持
- 错误处理与状态检查
完整代码实现
下面是完整的串口库实现代码:
/* stm32_uart.h - STM32串口通信库头文件 */
#ifndef __STM32_UART_H__
#define __STM32_UART_H__
#include "stm32f4xx_hal.h"
#include <stdint.h>
#include <stdbool.h>
/* 错误码定义 */
typedef enum {
UART_OK = 0,
UART_ERROR_PARAM,
UART_ERROR_INIT,
UART_ERROR_DEINIT,
UART_ERROR_TRANSMIT,
UART_ERROR_RECEIVE,
UART_ERROR_TIMEOUT
} UartError;
/* 波特率定义 */
typedef enum {
UART_BAUDRATE_9600 = 9600,
UART_BAUDRATE_115200 = 115200,
UART_BAUDRATE_460800 = 460800,
UART_BAUDRATE_921600 = 921600
} UartBaudrate;
/* 数据位定义 */
typedef enum {
UART_DATA_BITS_8 = UART_WORDLENGTH_8B,
UART_DATA_BITS_9 = UART_WORDLENGTH_9B
} UartDataBits;
/* 停止位定义 */
typedef enum {
UART_STOP_BITS_1 = UART_STOPBITS_1,
UART_STOP_BITS_2 = UART_STOPBITS_2
} UartStopBits;
/* 校验位定义 */
typedef enum {
UART_PARITY_NONE = UART_PARITY_NONE,
UART_PARITY_EVEN = UART_PARITY_EVEN,
UART_PARITY_ODD = UART_PARITY_ODD
} UartParity;
/* 硬件流控制定义 */
typedef enum {
UART_HWCONTROL_NONE = UART_HWCONTROL_NONE,
UART_HWCONTROL_RTS = UART_HWCONTROL_RTS,
UART_HWCONTROL_CTS = UART_HWCONTROL_CTS,
UART_HWCONTROL_RTS_CTS = UART_HWCONTROL_RTS_CTS
} UartHwControl;
/* 传输模式定义 */
typedef enum {
UART_MODE_TX = UART_MODE_TX,
UART_MODE_RX = UART_MODE_RX,
UART_MODE_TX_RX = UART_MODE_TX_RX
} UartMode;
/* 回调函数类型定义 */
typedef void (*UartTxCallback)(void* context, UartError error);
typedef void (*UartRxCallback)(void* context, uint8_t* data, uint32_t length, UartError error);
/* 串口设备结构 */
typedef struct {
UART_HandleTypeDef handle; /* HAL库串口句柄 */
DMA_HandleTypeDef* tx_dma_handle; /* 发送DMA句柄 */
DMA_HandleTypeDef* rx_dma_handle; /* 接收DMA句柄 */
uint8_t* rx_buffer; /* 接收缓冲区 */
uint32_t rx_buffer_size; /* 接收缓冲区大小 */
uint32_t rx_length; /* 接收数据长度 */
UartTxCallback tx_callback; /* 发送完成回调函数 */
UartRxCallback rx_callback; /* 接收完成回调函数 */
void* context; /* 回调函数上下文 */
bool is_initialized; /* 初始化状态 */
} UartDevice;
/* API函数声明 */
UartError Uart_Init(UartDevice* device, UART_HandleTypeDef* handle,
DMA_HandleTypeDef* tx_dma, DMA_HandleTypeDef* rx_dma,
uint8_t* rx_buffer, uint32_t rx_buffer_size);
UartError Uart_Config(UartDevice* device, UartBaudrate baudrate,
UartDataBits data_bits, UartStopBits stop_bits,
UartParity parity, UartHwControl hw_control,
UartMode mode);
UartError Uart_SetCallbacks(UartDevice* device, UartTxCallback tx_cb,
UartRxCallback rx_cb, void* context);
UartError Uart_Transmit(UartDevice* device, const uint8_t* data, uint32_t length);
UartError Uart_Transmit_DMA(UartDevice* device, const uint8_t* data, uint32_t length);
UartError Uart_Receive_DMA(UartDevice* device);
UartError Uart_Transmit_IT(UartDevice* device, const uint8_t* data, uint32_t length);
UartError Uart_Receive_IT(UartDevice* device, uint8_t* data, uint32_t length);
UartError Uart_Deinit(UartDevice* device);
const char* Uart_GetErrorString(UartError error);
/* HAL库回调函数,需要在用户代码中调用 */
void Uart_IRQHandler(UartDevice* device);
void Uart_TxCpltCallback(UartDevice* device);
void Uart_RxCpltCallback(UartDevice* device);
void Uart_ErrorCallback(UartDevice* device);
#endif /* __STM32_UART_H__ */
/* stm32_uart.c - STM32串口通信库实现文件 */
#include "stm32_uart.h"
/* 错误信息表 */
static const char* error_messages[] = {
"Success",
"Parameter error",
"Initialization error",
"Deinitialization error",
"Transmit error",
"Receive error",
"Timeout error"
};
/* 初始化串口设备 */
UartError Uart_Init(UartDevice* device, UART_HandleTypeDef* handle,
DMA_HandleTypeDef* tx_dma, DMA_HandleTypeDef* rx_dma,
uint8_t* rx_buffer, uint32_t rx_buffer_size) {
if (!device || !handle || (!rx_dma && (!rx_buffer || rx_buffer_size == 0))) {
return UART_ERROR_PARAM;
}
/* 初始化设备结构 */
device->handle = *handle;
device->tx_dma_handle = tx_dma;
device->rx_dma_handle = rx_dma;
device->rx_buffer = rx_buffer;
device->rx_buffer_size = rx_buffer_size;
device->rx_length = 0;
device->tx_callback = NULL;
device->rx_callback = NULL;
device->context = NULL;
device->is_initialized = false;
/* 初始化HAL UART */
if (HAL_UART_Init(&device->handle) != HAL_OK) {
return UART_ERROR_INIT;
}
device->is_initialized = true;
return UART_OK;
}
/* 配置串口参数 */
UartError Uart_Config(UartDevice* device, UartBaudrate baudrate,
UartDataBits data_bits, UartStopBits stop_bits,
UartParity parity, UartHwControl hw_control,
UartMode mode) {
if (!device || !device->is_initialized) {
return UART_ERROR_PARAM;
}
/* 配置串口参数 */
device->handle.Init.BaudRate = baudrate;
device->handle.Init.WordLength = data_bits;
device->handle.Init.StopBits = stop_bits;
device->handle.Init.Parity = parity;
device->handle.Init.HwFlowCtl = hw_control;
device->handle.Init.Mode = mode;
device->handle.Init.OverSampling = UART_OVERSAMPLING_16;
/* 应用配置 */
if (HAL_UART_Init(&device->handle) != HAL_OK) {
return UART_ERROR_INIT;
}
return UART_OK;
}
/* 设置回调函数 */
UartError Uart_SetCallbacks(UartDevice* device, UartTxCallback tx_cb,
UartRxCallback rx_cb, void* context) {
if (!device || !device->is_initialized) {
return UART_ERROR_PARAM;
}
device->tx_callback = tx_cb;
device->rx_callback = rx_cb;
device->context = context;
return UART_OK;
}
/* 同步发送数据 */
UartError Uart_Transmit(UartDevice* device, const uint8_t* data, uint32_t length) {
if (!device || !device->is_initialized || !data || length == 0) {
return UART_ERROR_PARAM;
}
if (HAL_UART_Transmit(&device->handle, (uint8_t*)data, length, 1000) != HAL_OK) {
return UART_ERROR_TRANSMIT;
}
return UART_OK;
}
/* 使用DMA异步发送数据 */
UartError Uart_Transmit_DMA(UartDevice* device, const uint8_t* data, uint32_t length) {
if (!device || !device->is_initialized || !data || length == 0) {
return UART_ERROR_PARAM;
}
if (HAL_UART_Transmit_DMA(&device->handle, (uint8_t*)data, length) != HAL_OK) {
return UART_ERROR_TRANSMIT;
}
return UART_OK;
}
/* 使用DMA异步接收数据 */
UartError Uart_Receive_DMA(UartDevice* device) {
if (!device || !device->is_initialized || !device->rx_dma_handle ||
!device->rx_buffer || device->rx_buffer_size == 0) {
return UART_ERROR_PARAM;
}
if (HAL_UART_Receive_DMA(&device->handle, device->rx_buffer, device->rx_buffer_size) != HAL_OK) {
return UART_ERROR_RECEIVE;
}
return UART_OK;
}
/* 使用中断异步发送数据 */
UartError Uart_Transmit_IT(UartDevice* device, const uint8_t* data, uint32_t length) {
if (!device || !device->is_initialized || !data || length == 0) {
return UART_ERROR_PARAM;
}
if (HAL_UART_Transmit_IT(&device->handle, (uint8_t*)data, length) != HAL_OK) {
return UART_ERROR_TRANSMIT;
}
return UART_OK;
}
/* 使用中断异步接收数据 */
UartError Uart_Receive_IT(UartDevice* device, uint8_t* data, uint32_t length) {
if (!device || !device->is_initialized || !data || length == 0) {
return UART_ERROR_PARAM;
}
if (HAL_UART_Receive_IT(&device->handle, data, length) != HAL_OK) {
return UART_ERROR_RECEIVE;
}
return UART_OK;
}
/* 反初始化串口设备 */
UartError Uart_Deinit(UartDevice* device) {
if (!device || !device->is_initialized) {
return UART_ERROR_PARAM;
}
/* 停止DMA传输 */
if (device->tx_dma_handle) {
HAL_DMA_Abort(device->tx_dma_handle);
}
if (device->rx_dma_handle) {
HAL_DMA_Abort(device->rx_dma_handle);
}
/* 反初始化HAL UART */
if (HAL_UART_DeInit(&device->handle) != HAL_OK) {
return UART_ERROR_DEINIT;
}
device->is_initialized = false;
return UART_OK;
}
/* 获取错误信息字符串 */
const char* Uart_GetErrorString(UartError error) {
if (error < 0 || error >= (sizeof(error_messages) / sizeof(error_messages[0]))) {
return "Unknown error";
}
return error_messages[error];
}
/* 串口中断处理函数 */
void Uart_IRQHandler(UartDevice* device) {
if (!device || !device->is_initialized) {
return;
}
HAL_UART_IRQHandler(&device->handle);
}
/* 发送完成回调函数 */
void Uart_TxCpltCallback(UartDevice* device) {
if (!device || !device->is_initialized || !device->tx_callback) {
return;
}
device->tx_callback(device->context, UART_OK);
}
/* 接收完成回调函数 */
void Uart_RxCpltCallback(UartDevice* device) {
if (!device || !device->is_initialized || !device->rx_callback || !device->rx_buffer) {
return;
}
/* 计算接收到的数据长度 */
if (device->rx_dma_handle) {
device->rx_length = device->rx_buffer_size - __HAL_DMA_GET_COUNTER(device->rx_dma_handle);
}
device->rx_callback(device->context, device->rx_buffer, device->rx_length, UART_OK);
/* 重新启动DMA接收 */
Uart_Receive_DMA(device);
}
/* 错误回调函数 */
void Uart_ErrorCallback(UartDevice* device) {
if (!device || !device->is_initialized || (!device->tx_callback && !device->rx_callback)) {
return;
}
UartError error = UART_ERROR_RECEIVE;
uint32_t error_code = HAL_UART_GetError(&device->handle);
if (error_code != HAL_UART_ERROR_NONE) {
/* 清除错误标志 */
__HAL_UART_CLEAR_OREFLAG(&device->handle);
__HAL_UART_CLEAR_NEFLAG(&device->handle);
__HAL_UART_CLEAR_FEFLAG(&device->handle);
__HAL_UART_CLEAR_PEFLAG(&device->handle);
/* 重新启动接收 */
if (device->rx_dma_handle) {
HAL_UART_Receive_DMA(&device->handle, device->rx_buffer, device->rx_buffer_size);
}
}
if (device->rx_callback) {
device->rx_callback(device->context, NULL, 0, error);
}
if (device->tx_callback) {
device->tx_callback(device->context, error);
}
}
库使用方法
-
初始化与配置:
// 定义UART句柄和DMA句柄 UART_HandleTypeDef huart1; DMA_HandleTypeDef hdma_usart1_tx; DMA_HandleTypeDef hdma_usart1_rx; // 定义接收缓冲区 uint8_t rx_buffer[256]; // 定义串口设备 UartDevice uart_device; // 初始化串口设备 Uart_Init(&uart_device, &huart1, &hdma_usart1_tx, &hdma_usart1_rx, rx_buffer, sizeof(rx_buffer)); // 配置串口参数 Uart_Config(&uart_device, UART_BAUDRATE_115200, UART_DATA_BITS_8, UART_STOP_BITS_1, UART_PARITY_NONE, UART_HWCONTROL_NONE, UART_MODE_TX_RX); // 设置回调函数 Uart_SetCallbacks(&uart_device, TxCallback, RxCallback, NULL);
-
数据发送:
// 同步发送 Uart_Transmit(&uart_device, (const uint8_t*)"Hello", 5); // 异步DMA发送 Uart_Transmit_DMA(&uart_device, (const uint8_t*)"World", 5);
-
数据接收:
// 启动DMA接收 Uart_Receive_DMA(&uart_device); // 接收回调函数 void RxCallback(void* context, uint8_t* data, uint32_t length, UartError error) { if (error == UART_OK && data && length > 0) { // 处理接收到的数据 } }
-
中断处理:
// 在中断处理函数中调用 void USART1_IRQHandler(void) { Uart_IRQHandler(&uart_device); } // HAL库回调函数实现 void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart) { if (huart == &uart_device.handle) { Uart_TxCpltCallback(&uart_device); } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { if (huart == &uart_device.handle) { Uart_RxCpltCallback(&uart_device); } } void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart) { if (huart == &uart_device.handle) { Uart_ErrorCallback(&uart_device); } }
多串口支持
如果需要支持多个串口设备,可以这样做:
// 定义多个串口设备
UartDevice uart1_device;
UartDevice uart2_device;
// 分别初始化和配置
Uart_Init(&uart1_device, &huart1, &hdma_usart1_tx, &hdma_usart1_rx, rx_buffer1, sizeof(rx_buffer1));
Uart_Init(&uart2_device, &huart2, &hdma_usart2_tx, &hdma_usart2_rx, rx_buffer2, sizeof(rx_buffer2));
// 分别配置和使用
Uart_Config(&uart1_device, UART_BAUDRATE_115200, ...);
Uart_Config(&uart2_device, UART_BAUDRATE_9600, ...);
注意事项
- DMA 配置:使用 DMA 功能时,需要正确配置 STM32CubeMX 中的 DMA 通道和中断
- 中断优先级:确保串口和 DMA 中断优先级设置合理
- 缓冲区管理:合理设置接收缓冲区大小,避免数据溢出
- 错误处理:实现完善的错误处理机制,处理帧错误、溢出错误等
- 低功耗模式:在进入低功耗模式前,确保正确处理串口和 DMA
这个串口库设计灵活,易于扩展,适合在 STM32 嵌入式系统中使用。根据实际需求,你可以进一步扩展其功能,如添加环形缓冲区、实现流控制等。