tanban/bsp/usart/bsp_usart.md

80 lines
4.2 KiB
Markdown
Raw Permalink Normal View History

2024-05-05 18:20:51 +08:00
# bsp_usart
<p align='right'>neozng1@hnu.edu.cn</p>
> 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文件内为私有函数和外部接口的定义。
## 类型定义
```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`(代表其使用的串口硬件具体是哪一个)以及用于解包数据的回调函数。
## 外部接口
```c
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的函数和变量
```c
static usart_instance *instance[DEVICE_USART_CNT];
```
这是bsp层管理所有串口实例的入口。
```c
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传输中断**后会被调用(说明收到了完整的一包数据),随后在里面根据中断来源,调用拥有产生了该中断的模块的协议解析函数进行数据解包;后者在串口传输出错的时候会被调用,重新开启接收。