实验笔记:校验和与串口通信实例 数据通信中的错误校验 校验和( CheckSum): 例如,被发送的数值为0xAB 0xCD 0xEF 0x01 0x020 x03,将它们的数值相加结果是0x026D,以十进制表示为621,与256相除后取余数,其值为109,再转换成十六进制为0x6D。 发送数据时在数据的尾端再加上一个字节0x6D,因此实际发送出去的数据成为: 0xAB 0xCD 0xEF 0x01 0x02 0x03 0x6D, 对方收到所发送的数据后会根据以上方式再进行一次计算,如果计算出来的结果是0x6D,表示此次发送数据是正确的。
校验和一般用于环境干扰不大或对数据准确性要求不算太高的场合,最大的优点是计算过程简单,占用单片机时间极少,缺点是有少数错误检查不出来,比如发送2个数据,100与200,校验和(100+200)%256=44,若数据发送过程中受到干扰100变成了110,200变成了190,接收方对数据校验(110+190)%256=44,与发送方计算的校验和相同,这时就把错误的数据当作正确的数据处理了。
例:串口通信的完整格式与校验和实例 通信协议:每次计算机串口助手向单片机发送5个字节的数据, 第一个字节为0x7E,数据开始标志(即帧头),后面3个字节为任意数据,最后一个字节为前4个数据和的低字节(高字节忽略),即校验和。 单片机接收到5个字节后,如果校验正确,发回第1字节0x7E作为帧头,2、3、4字节为接收的2、3、4字节加1后的数据,第5字节为前4个字节的校验和。 使用11.0592MHz内部R/C时钟,波特率9600,最为常见的N.8.1帧格式(无奇偶校验、8位数据位、1位停止位)。 测试方法:在STC串口助手发送区输入数据:7E,12,34,56,1A,选择HEX发送,HEX显示,单击发送后接收窗口立即显示7E,13,35,57,1D,则测试成功。如果串口助手向单片机发送数据后接收不到单片机返回数据,重点检查波特率设置是否正确。
51单片机串口接收和发送校验和测试程序:接收采用中断方式,发送采用查询方式,选择T2作串口波特率发生器,这样可以使T0,T1空出来做别的事。
关于格式化输出: %0x和%x都是以十六进制格式右对齐输出,输出的是无符号数。 在不指定占宽情况下以数据的实际宽度输出,而系统又自动消除左端的无效0,所以%0x和%x在显示效果上没有什么不同。 在指定占宽的情况下,在指定的输出占宽范围内,实际数据宽度不足时用%0x作控制的前面用0补齐,而用%x作控制的前面用空格补齐。如: printf(“%04X\n”); 表示十六进制显示,占4个字符的位置,不足的补0。 #define FMBEGIN 0x7e //帧头标志 uchar idata RecCount; //串口接收计数器,全局变量没有赋值以前,系统默认为0 uchar idata RecBuf[5]; //接收缓冲区 数据格式为:帧头+3字节数据+校验和 uchar idata SendBuf[5]; //发送缓冲区 数据格式为:帧头+3字节数据+校验和 //串行口1初始化 void UART1_init(void) { SCON = 0x50; //8位数据,可变波特率 AUXR |= 0x01; //串口1选择定时器2为波特率发生器 AUXR |= 0x04; //定时器2时钟为Fosc,即1T T2L = 0xE0; //设定定时初值 T2H = 0xFE; //设定定时初值
ES=1; //开启UART1中断
RecBuf[RecCount]=SBUF; if(RecCount==0) //判断帧头是否正确 }
for(i=0; i<len; i++) return(a); //主函数入口 UART1_init(); //串行口初始化 if(CheckValue==RecBuf[4]) }//while(1)
![]() |
|