通讯时采用应答方式,上位机每次发送8个字节(1帧数据)到下位机,然后看下位机的数据,下位机1个字节1个字节的上传数据到数据缓冲区,正常的话,下位机上传到数据缓冲区的数据有7位,如果不正确,丢掉这组数据,但是接下来怎么办?
串口设置9600,n,8,1 通讯协议MODBUS协议最后2位是CRC校验 8字节格式如下 01 03 03 65 00 01 CRC1 CRC2
收到数据正确的话是 01 03 02 XX XX CRC1 CRC2
串口设置9600,n,8,1 通讯协议MODBUS协议最后2位是CRC校验 8字节格式如下 01 03 03 65 00 01 CRC1 CRC2
收到数据正确的话是 01 03 02 XX XX CRC1 CRC2
开始码(1 Byte)、机号(1 Byte)、命令(1 or 2 Byte)、参数字节数(1 Byte)、参数内容(0 to 255 Byte)、异或校检码(1 Byte)、结束码(1 Byte)如:
0xB2 0x01 0x55 0x00 0xE6 0xB3
说明:
0xB2 开始码
0x01 机号
0x55 命令
0x00 参数字节数 因为这里是0,表示没有参数,所以下面就没有参数内容
0xE6 异或校检码 在VB中用 "Xor" 来运算,在 Keil C 中是 "^" 来运算,从包头开始向下面的数据运算
0xB3 结束码这样定义的好处是"有始有终",容易判断,而且机号的加入对无线通讯的多机数据通讯上也可以用。而且包的大小有格式和规律。
内容容易扩展也方便校验。在 Keil C 中,可以根据"开始码"和"步骤参数"决定是否开始接收数据,如果步骤不对或参数不对,从新调整接收步骤到开始状
态(就已经丢弃没用的包了),一直到收到"开始码"为止才开始进入下一步,若接下来的参数不符合条件,如机号不对,将步骤参数
设置回0重新开始接收"开始码",这样一直到接收完信息并收到结束码后再运算“异或校检码”,判断数据是否完整和正确,若校
检成功就对命令进行处理,无论校检结果如何,都将步骤设置回0,从新开始接收。
大致方法如下:#include <reg52.h>
#include <stdio.h>
#include <stdlib.h>
//常数定义
#define MyNumber 0x01 //当前机号
unsigned char Approach =0; //当前步骤
...
void COM_Event () interrupt 4
{
unsigned char dat;
unsigned char xorvalue = 0;
unsigned char nowxor = 0;
unsigned char xorcount = 0;
unsigned char i = 0;
bit TempLock=0;
if(RI)
{
dat = SBUF; //接收数据 SBUF 为单片机的接收发送缓冲寄存器
switch(Approach){
case 0:
//根据步骤,等待包头的出现,若不是包头数据就继续等待包头
if(dat==0xB2){
Approach = 1; //数据符合要求,将接收步骤调整为下一步
}else{
Approach = 0; //数据不符合接收步骤和相关的规定,放弃该数据(弃包处理)
}
break;
case 1:
//识别机号,判断数据是否应该发送到本机的,若不是就不必继续处理了
if(dat==MyNumber){
Approach = 2; //数据符合要求,将接收步骤调整为下一步
}else{
Approach = 0; //数据不符合接收步骤和相关的规定,放弃该数据(弃包处理)
}
break;
case 2:
...
在上位机中,也可以用类似的方法处理信息,其实 VB 处理这种信息很方便,建议多使用 CopyMemory 来处理信息,
然后得到数组后也是以类似 Keil C 的方法来处理数据,只是字节换成字节数组了,多花点心思处理一下数组,如果
发现了"开始码",可以用 CopyMemory 将整个数据段落向前移动,然后缩放数组,然后开始循环判断,若同一期间又
产生 OnComm 事件时,将新内容添加到数组结尾部分,其他的就由上一个事件来处理了。
当然,多事件处理可能比较麻烦,但如果仔细考虑一下还是很容易理解的,要衔接好,最重要的就是公共变量的使用。
希望以上的这些东西对你有所帮助。
是有7个字节吧
01 03 02 XX XX CRC1 CRC2 中的02指的是什么 长度控制吗