4.2 KiB
bsp_usart
TODO: 增加发送队列以解决短时间内调用
USARTSend()
发生丢包的问题,目前仅支持DMA。还需要提供阻塞和IT模式以供选择,参考bspiic和spi进行实现。 可以直接在发送函数的参数列表添加发送模式选择,或增加instance成员变量,并提供设置模式接口,两者各有优劣
使用说明
若你需要构建新的基于串口的module,首先需要拥有一个usart_instance
的指针用于操作串口对象。
需要在串口实例下设定接收的数据包的长度,实例对应的串口硬件(通过UART_HandleTypeDef
指定,如&huart1
),解析接收数据对应的回调函数这三个参数。然后,调用USARTRegister()
并传入配置好的usart_instance
指针即可。
若要发送数据,调用USARTSend()
。注意buffsize务必小于你创建的buff的大小,否则造成指针越界后果未知。
串口硬件收到数据时,会将其存入usart_instance.recv_buff[]
中,当收到完整一包数据,会调用设定的回调函数module_callback
(即你注册时提供的解析函数)。在此函数中,你可以通过usart_instance.recv_buff[]
访问串口收到的数据。
代码结构
.h文件内包括了外部接口和类型定义,以及模块对应的宏。c文件内为私有函数和外部接口的定义。
类型定义
#define DEVICE_USART_CNT 3 // C板至多分配3个串口
#define USART_RXBUFF_LIMIT 128 // if your protocol needs bigger buff, modify here
typedef void (*usart_module_callback)();
/* usart_instance struct,each app would have one instance */
typedef struct
{
uint8_t recv_buff[USART_RXBUFF_LIMIT]; // 预先定义的最大buff大小,如果太小请修改USART_RXBUFF_LIMIT
uint8_t recv_buff_size; // 模块接收一包数据的大小
UART_HandleTypeDef *usart_handle; // 实例对应的usart_handle
usart_module_callback module_callback; // 解析收到的数据的回调函数
} usart_instance;
-
DEVICE_USART_CNT
是开发板上可用的串口数量。 -
USART_RXBUFF_LIMIT
是串口单次接收的数据长度上限,暂时设为128,如果需要更大的buffer容量,修改该值。 -
usart_module_callback()
是模块提供给串口接收中断回调函数使用的协议解析函数指针。对于每个需要串口的模块,需要定义一个这样的函数用于解包数据。 -
每定义一个
usart_instance
,就代表一个串口的实例(对象)。一个串口实例内有接收buffer,单个数据包的大小,该串口对应的HAL handle
(代表其使用的串口硬件具体是哪一个)以及用于解包数据的回调函数。
外部接口
void USARTRegister(usart_instance *_instance);
void USARTSend(usart_instance *_instance, uint8_t *send_buf, uint16_t send_size);
-
USARTRegister
是用于初始化串口对象的接口,module层的模块对象(也应当为一个结构体)内要包含一个usart_instance
。在调用该函数之前,需要先对其成员变量
*usart_handle
,module_callback()
以及recv_buff_size
进行赋值。 -
USARTSend()
是通过模块通过其拥有的串口对象发送数据的接口,调用时传入的参数为串口实例指针,发送缓存以及此次要发送的数据长度(8-bit*n)。
私有函数和变量
在.c文件内设为static的函数和变量
static usart_instance *instance[DEVICE_USART_CNT];
这是bsp层管理所有串口实例的入口。
static void USARTServiceInit(usart_instance *_instance)
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
-
USARTServiceInit()
会被USARTRegister()
调用,开启接收中断 -
HAL_UARTEx_RxEventCallback()
和HAL_UART_ErrorCallback()
都是对HAL的回调函数的重定义(原本的callback是__week
修饰的弱定义),前者在发生IDLE中断或单次DMA传输中断后会被调用(说明收到了完整的一包数据),随后在里面根据中断来源,调用拥有产生了该中断的模块的协议解析函数进行数据解包;后者在串口传输出错的时候会被调用,重新开启接收。