项目开发中经常遇到uart的项目,各种不同外设,要求五花八门。在这过程中对uart的操作进行抽象。
封装:
1. 不同模式 polling it DMA
2. 是否启用空闲中断
3. 不同接口,ttl rs232 rs485 max3160
bsp_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 );
#endif
bsp_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->trans_record = (Record_Trans_Rcv_TypeDef *)malloc(sizeof(Record_Trans_Rcv_TypeDef));
// Handle->rcv_record = (Record_Trans_Rcv_TypeDef *)malloc(sizeof(Record_Trans_Rcv_TypeDef));
Handle->send_flag = 0;
Handle->send_tc_flag = 0;
Handle->transferring = 0;
Handle->enable_trans_gpio =NULL;
Handle->enable_trans_cplt_gpio =NULL;
Handle->obj =NULL;
Handle->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->rcv_record->buf = buf;
// uarthelper->rcv_record->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->trans_record->buf = buf;
uarthelper->trans_record->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->trans_mode)
{
case 0:
st = HAL_UART_Transmit(uarthelper->huart, buf, size , 0xFFFF);
return st;
break;
case 1:
st = HAL_UART_Transmit_IT(uarthelper->huart, buf, size);
return st;
break;
case 2:
/* 会出现 st ==2 huart->gState != HAL_UART_STATE_READY */
st = HAL_UART_Transmit_DMA(uarthelper->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->enable_idle_it == 0)
{
uarthelper->callback( uarthelper->obj, uarthelper->rcv_buf,uarthelper->rcv_size);
}
if (uarthelper->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->huart );
uarthelper->callback( uarthelper->obj, uarthelper->rcv_buf, size);
UART_HELPER_Start_Rcv(uarthelper, uarthelper->rcv_buf, uarthelper->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,&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->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( );
}