你说的是这个程序吧:http://www.51hei.com/bbs/dpj-3033-1.html 首先来理解程序开头的这句话的意思:“通信协议: 第1字节,MSB为1,为第1字节标志,第2字节,MSB为0,为非第一字节标志,其余类推……,最后一个字节为前几个字节后7位的异或校验和” 这里说的MSB就是指字节的最高位。“最后一个字节为前几个字节后7位的异或校验和”也就是说他把每个字节的最高位当作首字节的标志用了,因而每个字节所能表示的数只有0-127(7个bit),至于最高位的那一个bit,只和是否为首字节有关,只有首字节的最高位为“1”其他的字节最高位都为“0”。
再来看程序,我这里加上一些注释。 //串口接收中断函数 void serial () interrupt 4 using 3 //串口中断号为4,后面的using为寄存器组切换 { if (RI) //判断是否是接收中断 { unsigned char ch; //在这里定义了一个 字符变量 “ch” RI = 0 ; //清标志位 ch=SBUF; //这里把接收到的数据从串口缓存读到了变量ch里 if (ch> 127 ) //注意这里,ch>127的话其最高位必须是1才可以。也就是说,只有首字节才并且必然大于127。换句话说在这里判断了首字节 { //是首字节的话。。。 count3= 0 ; //给count3赋初值,这个count3就是用来计数接收到的字符的个数的。 inbuf1[count3]=ch; //把接收到的数据放到字符串inbuf1[]中,这inbuf1[]他定义的是全局变量,因而可以传回去。(他好像忘了去掉最高位的首字节标志了) checksum= ch- 128 ; //这就是计算所谓的校验和了吧,先把首位放进去,之所以减了个128就是要把最高位的标志减掉,只计算后七位的校验和。 } else //不是首字节的话。。。 { count3++; //接收计数自增 inbuf1[count3]=ch; //随着每次count3的自增,依次把接收到的数据放到字符串inbuf1[]中 checksum ^= ch; //依次按位异或,也就是说每收到一个字节都拿来异或一下。 if ( (count3==(INBUF_LEN- 1 )) && (!checksum) ) //逻辑表达式有点长啊,最外层是与,每个元素都为真才可以,前面count3==(INBUF_LEN- 1 )也就是说接收到了最后一个字符(他定义的INBUF_LEN =4,count3从0加到3,一共接收了四个字符),后面!checksum当依次按位异或的结果归0时才为真。 { read_flag= 1 ; //如果串口接收的数据达到INBUF_LEN个,且校验没错, //就置位取数标志 } } } }
“95 10 20 25” 这是四个字节的16进制数,全都转成二进制的数字看的清楚。 95——10010101 10——00010000 20——00100000 25——00100101 看到了吧,只有第一个0x95的最高位是1。其他的几个字节最高位都是0。 至于校验和,你查查每一纵列的1是不是都是偶数个(当然除了第一列)?偶数个1异或就是0。
按照这个格式,如果你发送 95 11 20 24 ,依然能得到返回数据. 95——10010101 11——00010001 20——00100000 24——00100100
不知道这样解释楼主是否明白了?
|