HAL 接收发送的数据包

接收发送数据包

HAL_UART_RxCpltCallback 函数的实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 接收 4 个字节的数据包
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart1){
		static uint8_t RxState = 0;
		static uint8_t pRxPacket = 0;
		
		uint8_t RxData = ByteRecv;
		// 开始接收数据包块
		if (RxState == 0){
			// 数据包头
			if (RxData == 0xFF){
				RxState = 1;
				pRxPacket = 0;
			}
			// 数据包内容
		} else if (RxState == 1){
			Serial_RxPacket[pRxPacket] = RxData;
			pRxPacket++;
			if (pRxPacket >= 4){
				RxState = 2;
			}
		} else if (RxState == 2){
			if (RxData == 0xFE){
				RxState = 0;
				Serial_RxFlag = 1;
			}
		}

		HAL_UART_Receive_IT (&huart1, &ByteRecv, 1);	
	}
}

首先判断 USART 的口是否为 huart1。

1
2
		static uint8_t RxState = 0;
		static uint8_t pRxPacket = 0;

初始化 RxStatepRxRacket 为 0。静态变量只会在第一次声明的时候进行随声明赋值。

如果要发送如下数据块:

ff 11 22 33 44 fe

这里 ff 是数据包头,fe 是数据包尾。

ByteRecv 即接收的数据传输到 RxData 内。

1
uint8_t RxData = ByteRecv;

数据包头

首先判断数据包头:

1
2
3
4
5
6
7
8
		// 开始接收数据包块
		if (RxState == 0){
			// 数据包头
			if (RxData == 0xFF){
				RxState = 1;
				pRxPacket = 0;
			}
		}

这里将 RxState 设为 1 算是一个标记开始记录

复位 pRxRacket 为 0 ,作为统计后面接收到数据数。

RxState 标记为 1 就开始接收数据了

数据

1
2
3
4
5
6
		} else if (RxState == 1){
			Serial_RxPacket[pRxPacket] = RxData;
			pRxPacket++;
			if (pRxPacket >= 4){
				RxState = 2;
			}

当 RxState 为 1 的时候,同时呢 pRxPacket 不大于 4,即接收的数据还不够多就继续接收数据。

这里的 pRxPacket 同时作为数组的索引

直到数据接收了 4 字节,将 RxState 变为 2,进入第三部分,取数据包尾:

1
2
3
4
5
	} else if (RxState == 2){
		if (RxData == 0xFE){
			RxState = 0;
			Serial_RxFlag = 1;
		}

这里主要是复位 RxStateSerial_RxFlag

在每次调用后都会调用这个函数打断中断接收为下次接收数据做准备

1
HAL_UART_Receive_IT (&huart1, &ByteRecv, 1);	

HAL_UART_Receive_IT 函数用于在中断模式下接收 UART 数据,这个函数可以让开发者接收到一定量的数据后通过回调函数 HAL_UART_RxCpltCallback() 来处理这些数据

其主要功能是在中断模式下启动 UART 来接收数据

使用步骤:

初始化UART:首先,需要使用HAL_UART_Init()函数初始化UART,配置波特率、字长、停止位、奇偶校验等参数。

调用HAL_UART_Receive_IT():在主函数或任何需要接收数据的地方调用此函数,传入UART句柄、数据缓冲区指针和接收数据的大小。

实现回调函数:实现HAL_UART_RxCpltCallback()回调函数,在此函数中处理接收到的数据。

HAL 库从中断服务程序进入 HAL 库串口处理函数 (HAL_UART_IRQHandler)的时候会关闭中断使能标志位 RXNE (一个寄存器上的字节位)

相当于程序运行到串口中断回调函数的时候中断使能标志位已经关闭了,此时如果外界再发数据包就不会触发中断

在 HAL_UART_Recieve_IT 中会调用 UART_Start_Receive_IT 重新打开 RXNE

UART_Start_Receive_IT 的本质功能和 UART_Start_Receive 是一致的都是吧串口接收缓冲区内的内容搬运到指定的内存区域。

但是 IT 的这个函数不会阻塞程序执行,其在中断回调函数中调用,而中断程序执行时相当于原有程序执行流杯打断,如果执行阻塞操作会影响 CPU 正常运行,所以这个函数没有 timeout 参数,

所有在中断函数中只能调用它来获取数据

萌ICP备20241614号