发表于:2007-02-23 09:31:00
楼主
计算CRC-16循环冗余校验码的程序开发
Program Development of Calculating CRC-16 Cyclic Redundancy Check Code
作者:詹根基 陈冲 Mail:zhan826@hotmail.com
【内容摘要】CRC-16是检测数据在发送过程中发生错误的常用校验方法,本文通过从工程应用的角度,讲述如何实现CRC-16的程序开发,并给出了Visual Basic和Visual C++程序代码,给从事工业控制的人员在写通信程序的时候提供一些有价值的参考。
一、前言
CRC的计算方式是将欲传输的数据块视为一堆连续位所构成的整个数值,将此数值除以一个特定的除数,通常以二进制表示,此除数称为生成多项式(ANSI CRC-16的生成多项式为:x16 + x15 + x2 + 1)。目前较常用的CRC位数目有8和16以及32,在这里只讲述如何写CRC位数目为16的程序。CRC位数目越大,数据的错误检测率则越高,但必须多花一些时间进行数据的计算。
二、CRC-16计算步骤
CRC-16的计算方法有两种:查表法与计算法,在这里只讲述计算法。本人在2000年在江西亚东水泥公司上班时,在某电力仪表上的说明书中摘录下来的计算CRC-16步骤如下:
1、 Load a 16-bit register with FFFF hex. Call this the CRC register.
2、 Exclusive OR the first 8-bit byte of the message with the low-order byte of the 16-bit CRC, putting the result in the CRC register.
3、 Shift the CRC register one bit to the right (toward the LSB), zero-filling the MSB. Extract and Examine.
4、 If the LSB was 1: Exclusive OR the CRC register with polynomial value A001 hex. If the LSB was 0: Repeat step 3 (another shift).
5、 Repeat step 3 and 4 until 8 shifts have been performed. When this is done, a complete 8-bit byte will have been processed.
6、 Repeat step 2 through 5 for the next 8-bit byte of them message.
7、 The final content of the CRC register is the CRC value.
中文解释如下:
1、定义一个初始值为FFFF的16位的变量,该变量称为CRC寄存器。(想想在程序中,应该怎么表示16位的变量呢?)
2、把欲发送或接收消息的高8位和CRC寄存器的底8位作异或运算,并把结果在赋到CRC寄存器。
3、CRC寄存器右移1位(朝最低位),同时最高位添零。取出并检查最低位是否为1。(Visual Basic 里如何做移位的运算呢?)
4、如果为1,则CRC寄存器与多项式A001异或;如果为0,则重复第3步的动作。(Visual Basic 里如何判断一个字节里某个位的值呢?)
5、重复3和4直到完成了8次移位。这样完整的8位字节将完成处理了。
6、对于下一个8位字节的处理就是重复第2步到第5步了
7、把所有的欲发送或接收消息这样处理后, CRC寄存器里的值就是我们最终需要得到的CRC校验码。
如果你能正确回答我的问题,那么恭喜你,你自己可以用Visual Basic写数据采集卡的控制程序了。
三、Visual Basic程序实现
以江阴长江斯菲尔电力仪表公司CD194E系列多功能电力仪表的MODBUS-RTU通讯协议的报文格式为例,该表通信报文格式使用的校验方式就是CRC-16。通过对地址01H、命令04H、数据地址005CH和数据长度0004H的CRC-16运算后得到主机请求数据报文的CRC16的校验码为31DBH。
程序界面
程序代码:
Private Sub cmdGenerate_Click()
Dim OutByte(7) As Byte, CRC16() As Byte, CRC16LO As Byte, CRC16HI As Byte, TempHI As Byte, TempLO As Byte
Dim i As Integer, j As Integer
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
OutByte(0) = Val("&H" & txtOutByte(0).Text)
OutByte(1) = Val("&H" & txtOutByte(1).Text)
OutByte(2) = Val("&H" & txtOutByte(2).Text)
OutByte(3) = Val("&H" & txtOutByte(3).Text)
OutByte(4) = Val("&H" & txtOutByte(4).Text)
OutByte(5) = Val("&H" &am