1、在使用串口接收自定义协议指令时,需要串口解析收到的是什么指令,举例通信报文为
上位机->单片机
名称 | 长度 | 备注 | |
帧头 | 1Byte | 0x5A 0x5A | |
帧长度 | 1Byte | 数据包的长度0x00-0xFF | |
数据包 | 命令字 | 1Byte | 功能标识 |
数据 | 可以为空 | ||
校验 | 1Byte | 数据包所有字节按位异或 |
单片机->上位机
名称 | 长度 | 备注 | |
帧头 | 1Byte | 0xA5 0xA5 | |
帧长度 | 2Byte | 数据包的长度0x0000-0xFFFF | |
数据包 | 命令字 | 1Byte | 功能标识 |
数据 | 可以为空 | ||
校验 | 1Byte | 数据包所有字节按位异或 |
那么,在单片机机收到上位机的指令后需要解析命令字是什么,然后做相应的功能处理。
2、此时的串口接收解析处理函数可以采用状态机的方法来处理:
首先,在main函数中的while循环之前第一次接收数据
HAL_UART_Receive_IT(&huart3,&ble_rec_buf,1);//接收数据
然后中断回调函数如下编写
//接收回调函数---接收数据解析
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart==&huart3)
{
switch(usart3_state)
{
case 0: //如果收不到0x5a,则跳出switch,如果收到则进入case1,blue_receive_buf[0]为0x5a
blue_receive_buf[0]=ble_rec_buf;
if(blue_receive_buf[0]==0x5a)
{
usart3_state=1;
usart3_cnt=1;
}
else
{
usart3_state=0;
}
break;
case 1: //在case1中接着接收数据0x5a 0x01(长度) 0x01(命令),分别存放在blue_receive_buf[1]、blue_receive_buf[2]、blue_receive_buf[3]
blue_receive_buf[usart3_cnt]=ble_rec_buf;
usart3_cnt++;
if(usart3_cnt>3)
{
usart3_state=2;
}
else
{
usart3_state=1;
}
break;
case 2://最后接收校验码blue_receive_buf[4],判断是否为0x01
blue_receive_buf[usart3_cnt]=ble_rec_buf;
if(blue_receive_buf[usart3_cnt]==0x01)//如果收到的校验码正确
{
switch(blue_receive_buf[2])
{
case 1://如果命令为0x01,则为查询历史数据
blue_transmite_flag=1;
break;
case 2:
break;
case 3:
break;
default:
break;
}
}
break;
default:
break;
}
HAL_UART_Receive_IT(&huart3, &ble_rec_buf, 1);
}
}
这种方法可以解析不同的通信指令,而不存在串口收到的数据是不定长的而无法处理的问题。
标签:blue,break,自定义,receive,usart3,STM32,串口,buf,1Byte From: https://blog.csdn.net/jacklood/article/details/140693807