{
//先移位操作再将缓冲区内容与帧头进行比较
RXFH[0] = RXFH[1]; RXFH[1] = RXFH[2]; RXFH[2] = Rx_Data;
if((RXFH[0]==FRM_H)&&(RXFH[1]==FRM_L))
{
RXFHOK = 1; //正常接收到帧头标志位置1
Rx_Num = RXFH[2]; }
} } if(TI) {
TI = 0; } }
看到这里你是不是感觉这种做法有点巧妙呢?判断帧头就像把接收到的数据放到一个三字节的窗口中,自己盯着窗口找帧头,如果发
现帧头匹配,那么我就要处理接收到帧头的程序了。接收到帧头处理方法为:每接收到一个字节,则接收到的数据位置Rx_POS加1,如果接收的数据长度等于Rx_Num,则对表示一帧数据接收完成,则应给接收一帧完整数据标志位置位,同时将接收数据位置Rx_P清零,并将接收到帧头标识为清零。详见下面的代码(增加的部分用浅红色标识): 代码3:
void UART1_ISR() interrupt 4 {
unsigned char Rx_Data; if(RI) {
Rx_Data = SBUF;//读取串口缓冲区数据 RI = 0; //清除串口中断请求 }
if(!RXFRMOK) //如果没有接收到完整帧 {
if(!RXFHOK) //如果没有接收到帧头 ;初始值是0肯定是先进入这个循环,先接受5A A5 03嘛!!!!! {
//先移位操作再将缓冲区内容与帧头进行比较
RXFH[0] = RXFH[1];
RXFH[1] = RXFH[2]; RXFH[2] = Rx_Data;
if((RXFH[0]==FRM_H)&&(RXFH[1]==FRM_L))
{
RXFHOK = 1; //正常接收到帧头标志位置1
Rx_Num = RXFH[2];
goto TX: //接收完数据当然要跳出去了,不能把数据长度存放到数据中了 } }
if(RXFHOK) ;此处的IF和上面
的IF并不是并行的,是接受完前面三个字节,RXFHOK为1后才进入到这个IF判断的1
{
RXBUF[Rx_POS] = Rx_Data; Rx_POS ++;
if(Rx_POS > Rx_Num-1) {
RXFRMOK = 1; RXFHOK = 0;
Rx_POS = 0; }
} } TX: if(TI) {
TI = 0; } }
以上代码3基本上对本文开始的那段协议完成了解析。是不是很简单?细心看代码3的人可能会一眼看出来,你这代码接收到一帧完整数据后,RXFRMOK就为1了,后续该怎么处理呢?应该有个归零的过程啊,不然怎么再次接收数据呢?这个问题问得很好,这里我没有把主程序写出来,因为解析基本上在串口中断里完成了,当接收到一帧完整数据,其中某一个数据必定有着特定的用途,假设RX_BUF[0]的数据代表接受的数据代表的命令,那么,我在主程序中判断RX_BUF[0]的值即可,处理完相关任务,我们必须将RXFRMOK清零,那么程序就可以再次接收数据帧了。
其中有一个特别需要注意的是,有些人没有注意分析这些代码,判断错误的数据,导致不能解析该协议,这里特别说明一下:假设单片机接收一帧数据为 0xaa 0xbb 0x03 0x40 0x01 0x06,那么RX_BUF中数据是什么呢?告诉你,只有后面三个字节,即0x40 0x01 0x06。解
析协议的时候已经将帧头和数据长度这三个字节去掉了。
有了通信协议,就可以做一个组网的系统,例如医院里的医护系统,工厂的工业控制系统,应用范围广,安全高效!值得学习!如有兴趣,可发邮件至huzhiqianglz@163.com与我交流。本文转载请注明出处,文中若有错别字,在所难免,请告之本人修正,谢谢! 其他类型的协议解析暂未整理,如有空再写,敬请关注!