
摘要本文介绍了一套针对 STM32 UART 外设的通用封装方案通过抽象不同传输模式polling、IT、DMA、接口类型TTL、RS232、RS485、MAX3160以及空闲中断等配置将串口初始化、收发、回调与 GPIO 控制统一封装为可复用的接口并给出了 bsp_uart.h、bsp_uart.c 及调用示例便于在不同项目中快速适配串口需求。项目开发中经常遇到 UART 的项目各种不同外设要求五花八门。在这过程中对 UART 的操作进行抽象。封装1. 不同模式 polling、IT、DMA2. 是否启用空闲中断3. 不同接口TTL、RS232、RS485、MAX3160bsp_uart.h#ifndef __BSP_UART_H #define __BSP_UART_H #include stm32f4xx.h /** 封装不同使用类型串口 232 485 max3160 包含发送回调的GPIO操作 其他回调外部处理 / / 485 3160 启用一个 两个接口都有 MAX3160_ENABLE */ #define MAX485_ENABLE 0 #define MAX3160_ENABLE 1 #ifdef __cplusplus extern C { #endif #include stdlib.h #include main.h typedef enum { Uart_Interface_Default 0x00U, Uart_Interface_485 0x01U, Uart_Interface_Max3160_232 0x02U, Uart_Interface_Max3160_485 0x03U, } Uart_Interface_Type_Typedef; typedef enum { Uart_Trans_Polling 0x00U, Uart_Trans_IT 0x01U, Uart_Trans_DMA 0x02U, } Uart_Transmode_TypeDef; typedef enum { Uart_IDLE_IT_DISABLE 0x00U, Uart_IDLE_IT_ENABLE 0x01U, } Uart_IDLE_Enable_TypeDef; typedef struct { uint32_t size; uint8_t *buf; }Record_Trans_Rcv_TypeDef; /* ----------------------- variables ---------------------------------*/ // extern UART_HandleTypeDef huart3; // UART_HandleTypeDef *puarthelper huart3; typedef void ( *enable_func_gpio) (void); typedef int ( *callback_fun) (void *obj, void *buf, uint16_t size); typedef struct { UART_HandleTypeDef huart; Uart_Interface_Type_Typedef interface_type; / 0: default(TTL 232), 1: 485 ,2:3160-232 3: 3160-485*/ Uart_IDLE_Enable_TypeDef enable_idle_it; Uart_Transmode_TypeDef trans_mode; /* 0 :polling, 1: IT 2: DMA*/ Uart_Transmode_TypeDef rcv_mode; Record_Trans_Rcv_TypeDef *trans_record; // Record_Trans_Rcv_TypeDef *rcv_record; // uint8_t *trans_buf; // uint16_t trans_size; uint8_t *rcv_buf; uint16_t rcv_size; volatile uint8_t send_flag; volatile uint8_t send_tc_flag; /* 0 开始发送 1 发送完成*/ volatile uint8_t transferring; // uint32_t timebase; enable_func_gpio enable_trans_gpio; enable_func_gpio enable_trans_cplt_gpio; void * obj; callback_fun callback; // 这个是供外部调用的 中断是统一管理的 中断会找到这里的接收回调然后返回回去 // #if MAX485_ENABLE // GPIO_TypeDef *de485_gpio; // uint16_t de485_pin; // uint8_t de485; // #endif // #if MAX3160_ENABLE // GPIO_TypeDef *de485_gpio; // uint16_t de485_pin; // GPIO_TypeDef *sel_gpio; // GPIO_TypeDef *dplx_gpio; // uint16_t sel_pin; // uint16_t dplx_pin; // uint8_t sel; // uint8_t dplx; // #endif // uint8_t dplx; // uint8_t sel; // uint8_t de485; }UART_HELPER_TypeDef; extern UART_HELPER_TypeDef *uarthelper; UART_HELPER_TypeDef * UART_HELPER_Init( ); void UART_HELPER_Set_Huart(UART_HELPER_TypeDef * uarthelper, UART_HandleTypeDef *huart); int UART_HELPER_Set_Interface_Type(UART_HELPER_TypeDef * uarthelper, uint8_t interface_type); int UART_HELPER_Setup_Trans_mode( UART_HELPER_TypeDef * uarthelper, uint8_t trans_mode ); int UART_HELPER_Setup_Rcv_mode( UART_HELPER_TypeDef * uarthelper, uint8_t rcv_mode ); int UART_HELPER_Set_trans_GPIO( UART_HELPER_TypeDef * uarthelper, enable_func_gpio trans_gpio_func ); int UART_HELPER_Set_trans_cplt_GPIO( UART_HELPER_TypeDef * uarthelper, enable_func_gpio trans_cplt_gpio_func ); int UART_HELPER_Set_enable_idle( UART_HELPER_TypeDef * uarthelper, uint8_t enable_idle); int UART_HELPER_Set_Rcv_Buf( UART_HELPER_TypeDef * uarthelper, uint8_t * buf, uint16_t size); int UART_HELPER_Set_Trans_Buf( UART_HELPER_TypeDef * uarthelper, uint8_t * buf, uint16_t size); int UART_HELPER_Set_Callback( UART_HELPER_TypeDef * uarthelper, void *obj, callback_fun func); int UART_HELPER_Trans(UART_HELPER_TypeDef * uarthelper, uint8_t *buf, uint16_t size); // int __UART_HELPER_Trans(UART_HELPER_TypeDef * uarthelper , uint8_t buf, uint16_t size); int UART_HELPER_Trans_TxCplt_Callback( UART_HELPER_TypeDef * uarthelper ); / 接收方式 也有三种类型 */ int UART_HELPER_Start_Rcv(UART_HELPER_TypeDef * uarthelper, uint8_t *buf, uint16_t size); int UART_HELPER_RCV_Cplt_Callback( UART_HELPER_TypeDef * uarthelper ); int UART_HELPER_RCV_IDLE_Callback( UART_HELPER_TypeDef * uarthelper, uint16_t size ); #endifbsp_uart.c#include bsp_uart.h #include elog.h UART_HELPER_TypeDef * UART_HELPER_Init( ) { UART_HELPER_TypeDef *Handle (UART_HELPER_TypeDef *)malloc(sizeof(UART_HELPER_TypeDef)); if (Handle NULL) { return NULL; } Handle-interface_type Uart_Interface_Default; Handle-enable_idle_it Uart_IDLE_IT_DISABLE; Handle-trans_mode Uart_Trans_Polling; Handle-rcv_mode Uart_Trans_Polling; Handle-gt;trans_record (Record_Trans_Rcv_TypeDef *)malloc(sizeof(Record_Trans_Rcv_TypeDef)); // Handle-gt;rcv_record (Record_Trans_Rcv_TypeDef *)malloc(sizeof(Record_Trans_Rcv_TypeDef)); Handle-gt;send_flag 0; Handle-gt;send_tc_flag 0; Handle-gt;transferring 0; Handle-gt;enable_trans_gpio NULL; Handle-gt;enable_trans_cplt_gpio NULL; Handle-gt;obj NULL; Handle-gt;callback NULL; return Handle; } void UART_HELPER_Set_Huart(UART_HELPER_TypeDef * uarthelper, UART_HandleTypeDef *huart) { uarthelper-huart huart; } int UART_HELPER_Set_Interface_Type(UART_HELPER_TypeDef * uarthelper, uint8_t interface_type) { uarthelper-interface_type interface_type; return 0; } int UART_HELPER_Setup_Trans_mode( UART_HELPER_TypeDef * uarthelper, uint8_t trans_mode ) { /* 0 :polling, 1: IT 2: DMA*/ uarthelper-trans_mode trans_mode; uarthelper-rcv_mode trans_mode; return 0; } int UART_HELPER_Setup_Rcv_mode( UART_HELPER_TypeDef * uarthelper, uint8_t rcv_mode ) { /* 0 :polling, 1: IT 2: DMA*/ uarthelper-rcv_mode rcv_mode; return 0; } int UART_HELPER_Set_trans_GPIO( UART_HELPER_TypeDef * uarthelper, enable_func_gpio trans_gpio_func ) { uarthelper-enable_trans_gpio trans_gpio_func; return 0; } int UART_HELPER_Set_trans_cplt_GPIO( UART_HELPER_TypeDef * uarthelper, enable_func_gpio trans_cplt_gpio_func ) { // enable rcv uarthelper-enable_trans_cplt_gpio trans_cplt_gpio_func; return 0; } int UART_HELPER_Set_enable_idle( UART_HELPER_TypeDef * uarthelper, uint8_t enable_idle) { uarthelper-enable_idle_it enable_idle; return 0; } int UART_HELPER_Set_Rcv_Buf( UART_HELPER_TypeDef * uarthelper, uint8_t * buf, uint16_t size) { uarthelper-rcv_buf buf; uarthelper-rcv_size size; // uarthelper-gt;rcv_record-gt;buf buf; // uarthelper-gt;rcv_record-gt;size size; return 0; } int UART_HELPER_Set_Trans_Buf( UART_HELPER_TypeDef * uarthelper, uint8_t * buf, uint16_t size) { // uarthelper-trans_buf buf; // uarthelper-trans_size size; uarthelper-gt;trans_record-gt;buf buf; uarthelper-gt;trans_record-gt;size size; return 0; } int UART_HELPER_Set_Callback( UART_HELPER_TypeDef * uarthelper, void *obj, callback_fun func) { uarthelper-obj obj; uarthelper-callback func; return 0; } int UART_HELPER_Start_Rcv(UART_HELPER_TypeDef * uarthelper, uint8_t buf, uint16_t size) { int st; switch ( uarthelper-rcv_mode) { case 0: st HAL_UART_Receive(uarthelper-huart, buf, size , 0xFFFF); return st; break; case 1: st HAL_UART_Receive_IT(uarthelper-huart, buf, size); return st; break; case 2: / 会出现 st 2 huart-gState ! HAL_UART_STATE_READY */ if (uarthelper-enable_idle_it 1) { // log_i(dma rcv idle en... ); __HAL_UART_ENABLE_IT(uarthelper-huart, UART_IT_IDLE); } st HAL_UART_Receive_DMA(uarthelper-huart, buf, size); // log_i(dma rcv ... ); return st; break; default: break; } return st; } int UART_HELPER_Trans(UART_HELPER_TypeDef * uarthelper, uint8_t *buf, uint16_t size ) { int st; uarthelper-transferring 1; if (uarthelper-enable_trans_gpio ! NULL) { uarthelper-enable_trans_gpio(); } switch ( uarthelper-gt;trans_mode) { case 0: st HAL_UART_Transmit(uarthelper-gt;huart, buf, size , 0xFFFF); return st; break; case 1: st HAL_UART_Transmit_IT(uarthelper-gt;huart, buf, size); return st; break; case 2: /* 会出现 st 2 huart-gt;gState ! HAL_UART_STATE_READY */ st HAL_UART_Transmit_DMA(uarthelper-gt;huart, buf, size); return st; break; default: break; } return st; } int UART_HELPER_Trans_TxCplt_Callback( UART_HELPER_TypeDef * uarthelper ) { // log_i( uarthelper tc callback...........); uarthelper-transferring 0; if (uarthelper-enable_trans_cplt_gpio ! NULL) { // log_i( uarthelper tc callback... not null........); uarthelper-enable_trans_cplt_gpio(); } return 0; } int UART_HELPER_RCV_Cplt_Callback( UART_HELPER_TypeDef * uarthelper ) { log_i( UART_HELPER_RCV_Cplt_Callback ........); // TODO if (uarthelper-gt;enable_idle_it 0) { uarthelper-gt;callback( uarthelper-gt;obj, uarthelper-gt;rcv_buf,uarthelper-gt;rcv_size); } if (uarthelper-gt;enable_idle_it 1) { // idle 中断处理 do nothing } return 0; } int UART_HELPER_RCV_IDLE_Callback( UART_HELPER_TypeDef * uarthelper, uint16_t size ) { // TODO // if (uarthelper-rcv_mode 0) // { // HAL_UART_DMAStop( uarthelper-huart ); // } HAL_UART_DMAStop( uarthelper-gt;huart ); uarthelper-gt;callback( uarthelper-gt;obj, uarthelper-gt;rcv_buf, size); UART_HELPER_Start_Rcv(uarthelper, uarthelper-gt;rcv_buf, uarthelper-gt;rcv_size); return 0; }调用方法typedef struct { int (*init)(void); void (*port)(void); int (*test)(void); void (*start)(void); void (*stop)(void); osMessageQueueId_t cmdQueue; // 队列可选 volatile Module_PH_State_TypeDef state; uint8_t data_ok; /* 接收数据完整可以处理 */ uint8_t result_buf[1024]; uint8_t size_received; uint64_t timebase_ticks; uint64_t timeout_ticks; uint8_t event_flag; }PH_TypeDef; PH_TypeDef ph { PH_Init, PH_Port, PH_Test, PH_Start, PH_Stop, NULL, 0, // state 0, // data_ok {0}, // buf 0, // size_received 0, // time base 1000, // timeout ticks, 1000ms 1S 0, // event_flag }; int PH_Init( ) { ph_uart_helper UART_HELPER_Init( ); if (ph_uart_helper NULL) return -1; // TODO 接口 UART_HELPER_Set_Huart( ph_uart_helper, pPHUart ); UART_HELPER_Set_Interface_Type(ph_uart_helper, Uart_Interface_Max3160_485); // 传输 UART_HELPER_Setup_Trans_mode( ph_uart_helper, Uart_Trans_DMA); // UART_HELPER_Setup_Rcv_mode( ph_uart_helper, Uart_Trans_IT ); UART_HELPER_Set_enable_idle( ph_uart_helper, Uart_IDLE_IT_ENABLE); // 回调GPIO 操作 数据操作 UART_HELPER_Set_trans_GPIO( ph_uart_helper, PH_Trans_GPIO ); // enbale rcv UART_HELPER_Set_trans_cplt_GPIO( ph_uart_helper, PH_Trans_Cplt_GPIO ); UART_HELPER_Set_Callback( ph_uart_helper,amp;ph, PH_CallBack ); // 设置 Buf UART_HELPER_Set_Rcv_Buf(ph_uart_helper, PH_RCV_BUF, sizeof(PH_RCV_BUF)); UART_HELPER_Set_Trans_Buf( ph_uart_helper, PH_TRANS_BUF, sizeof(PH_TRANS_BUF) ); // GPIO 操作 switch (ph_uart_helper-gt;interface_type) { case Uart_Interface_Default: break; case Uart_Interface_485: usart6_send_enable(); break; case Uart_Interface_Max3160_232: PH_MAX3160_232(); break; case Uart_Interface_Max3160_485: max3160_485_receive_mode(); break; default: break; } ph.state PH_State_Waiting; ph.timebase_ticks osKernelGetTickCount( ); }