嵌入式开发之stm32串口库封装开发

下面为你分享一个基于 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);
    }
}

库使用方法

  1. 初始化与配置

    // 定义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);
    
  2. 数据发送

    // 同步发送
    Uart_Transmit(&uart_device, (const uint8_t*)"Hello", 5);
    
    // 异步DMA发送
    Uart_Transmit_DMA(&uart_device, (const uint8_t*)"World", 5);
    
  3. 数据接收

    // 启动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) {
            // 处理接收到的数据
        }
    }
    
  4. 中断处理

    // 在中断处理函数中调用
    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, ...);

注意事项

  1. DMA 配置:使用 DMA 功能时,需要正确配置 STM32CubeMX 中的 DMA 通道和中断
  2. 中断优先级:确保串口和 DMA 中断优先级设置合理
  3. 缓冲区管理:合理设置接收缓冲区大小,避免数据溢出
  4. 错误处理:实现完善的错误处理机制,处理帧错误、溢出错误等
  5. 低功耗模式:在进入低功耗模式前,确保正确处理串口和 DMA

这个串口库设计灵活,易于扩展,适合在 STM32 嵌入式系统中使用。根据实际需求,你可以进一步扩展其功能,如添加环形缓冲区、实现流控制等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

start_up_go

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值