以电表的读取数据为例,通过STM32的串口接收中断将电表的数据解析出来,因为要兼容两种协议,分开解析较麻烦,想着合在一起,将真正要读取的数据按照顺序存储在一个数组之中。
首先简述下两种协议关于读取数据的区别:
1、97规约的读取数据控制码为0x01,07规约为0x11;
2、97的数据域为2个字节,07的数据域为4个字节;
3、设备应答的控制码97为0x81,07为0x91;
相同的格式:
不超过四个的0xFE+0x68的数据包头+6个字节的电表地址+0x68+控制码+数据长度+数据域+数据(N1,N2...Nn)+校验码+0x16
所以将设备应答的数据在中断中这样解析:
void USART1_IRQHandler(void)? ? ? ? ? ? ? ? ? ? { ?? ?u8 res; ?? ?static u8 count,num,t;
?? ?if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收到数据 ?? ?{ ?? ??? ?res =USART_ReceiveData(USART1);//;读取接收到的数据USART2->DR? ? ? ? ?? ??? ? ?switch(count){ ?? ??? ??? ?case 0: if(res==0xFE)count=0;else if(res==0x68)count++;break;//判断包头 ?? ??? ??? ?case 1: RS485_RX_BUF_1[t]=res;t++;if(t==6)count++;break;//将电表6个字节地址存入数组之中 ?? ??? ??? ?case 2: if(res==0x68)count++;break;//包头 ?? ??? ??? ?case 3: RS485_RX_BUF_1[t]=res;count++;t++;break;//将响应的控制码放入数组 ?? ??? ??? ?case 4: num=res;RS485_RX_BUF_1[t]=num;t++;count++;break;//将数据长度放入数组 ?? ??? ??? ?case 5: RS485_RX_BUF_1[t]=res;t++;if((num+8)==t)count++;break;//数据存入数组 ?? ??? ??? ?case 6: count++; break;//校验码位 ?? ??? ??? ?case 7:if(res==0x16){? ? ? ? ? //结束符? 清空数组
? ? ? ? ? ? count=0;t=0;
? ? ? ? }??break;?? ? ?? ??}?
}
RS485_RX_BUF_1[t]数组可以定义成全局变量,最后分析此数组里的数据即可得到关于电表的信息。主要要找到数组中的数据长度,通过数据长度判断读取数据的位置。
如果用的实时操作系统,即将数组RS485_RX_BUF_1数据发送到队列后清零(用中断的API函数发送队列)。另一个任务读取队列数据即可。
|