阅读量:0
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); } }
这种方法可以解析不同的通信指令,而不存在串口收到的数据是不定长的而无法处理的问题。