前言

若无特殊说明,串口配置默认为115200 Baud,8位数据位,1位停止位,无校验位。

中断,回调?

中断:是一种硬件机制,当外设或特定事件发生时,CPU会暂停当前任务,转而执行对应的中断服务程序(ISR),处理完毕后再返回原任务。

中断回调:是软件层面的机制。当中断发生并被ISR捕获后,HAL库会自动调用用户自定义的回调函数,用户仅需在回调中编写具体的处理逻辑。

核心思路:每接收1个字节数据,就触发1次中断,进入中断回调函数。若检测到包头,开始将数据存入缓冲区,并更新索引。达到指定长度,或接收到包尾后,进入数据处理函数。

CUBEMX配置

新建工程

新建CUBEMX工程(略),打开串口配置页面,选择异步模式,其余配置保持默认。

uart1

配置中断

在NVIC配置页面,勾选USARTx global interrupt,启用串口中断。

uartit1

生成代码

配置工程名、Code Generator等基本设置,生成代码。

uart4

Keil代码

函数介绍

HAL库的普通串口中断接收函数如下:

1
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

其中,三个参数分别为串口号、首位接收数据地址、数据长度。

串口中断回调函数如下:

1
2
3
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
// 接收完成后的处理
}

初始化

  • 定义接收缓冲区、数据索引和数据存放缓冲区变量

    1
    2
    3
    4
    5
    /* USER CODE BEGIN PV */
    uint8_t rx_buf = 0;
    uint8_t rx_idx = 0;
    uint8_t UART1_RX_BUF[32];
    /* USER CODE END PV */
  • 开启串口中断接收

    1
    2
    3
    /* USER CODE BEGIN 2 */
    HAL_UART_Receive_IT(&huart1, &rx_buf, 1);
    /* USER CODE END 2 */

重写中断回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* USER CODE BEGIN 4 */
// 假设数据包格式为:AA BB(包头) + 12字节数据 + CC DD(包尾)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart->Instance == USART1){
if(rx_idx == 0 && rx_buf != 0xAA){ // 检验包头1
HAL_UART_Receive_IT(&huart1, &rx_buf, 1); // 若包头错误则不处理数据,直接重启接收
}
else{ // 包头正确,存数据
UART1_RX_BUF[rx_idx++] = rx_buf;
if(rx_idx == 16){ // 达到数据长度
rx_idx = 0;
if(UART1_RX_BUF[1] == 0xBB){ // 检验包头2
DataReceive(UART1_RX_BUF); // 数据处理函数,由用户实现,建议含包尾检验
}
}
HAL_UART_Receive_IT(&huart1, &rx_buf, 1);
}
}
}
/* USER CODE END 4 */
  • 若包中数据长度未知,则可以将if(rx_idx == 16)的判定条件改为if(rx_idx >= 2 && UART1_RX_BUF[rx_idx-1] == 0xDD && UART1_RX_BUF[rx_idx-2] == 0xCC),即检测到包尾时进入数据处理函数。