计算CRC-16循环冗余校验码的程序开发 点击:4835 | 回复:8



opcfan

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:62帖 | 58回
  • 年度积分:0
  • 历史总积分:667
  • 注册:2004年9月29日
发表于: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



KingLion

  • 精华:2帖
  • 求助:0帖
  • 帖子:86帖 | 1155回
  • 年度积分:0
  • 历史总积分:2681
  • 注册:2002年2月26日
发表于:2007-02-27 14:21:00
1楼
很好的帖子!!!
顶一顶!!!

昆仑摩勒

  • 精华:1帖
  • 求助:1帖
  • 帖子:32帖 | 446回
  • 年度积分:0
  • 历史总积分:1058
  • 注册:2004年11月22日
发表于:2007-03-07 14:11:00
2楼
不得不顶啊 呵呵 好!

直流电机

  • 精华:1帖
  • 求助:0帖
  • 帖子:5帖 | 39回
  • 年度积分:0
  • 历史总积分:125
  • 注册:2006年1月21日
发表于:2007-11-21 14:17:00
3楼
VB里右移采用/2方法来做啊,如果是学过汇编语言的在学高级语言,就简单多了。

众源

  • 精华:0帖
  • 求助:0帖
  • 帖子:1帖 | 25回
  • 年度积分:0
  • 历史总积分:29
  • 注册:2006年1月18日
发表于:2007-12-11 12:12:00
4楼
顶一下!

ranranplay

  • 精华:1帖
  • 求助:0帖
  • 帖子:18帖 | 382回
  • 年度积分:0
  • 历史总积分:773
  • 注册:2005年9月27日
发表于:2008-01-04 11:57:00
5楼
http://www.gongkong.com/tech/detail.asp?id=423164

xatd2001

  • 精华:0帖
  • 求助:0帖
  • 帖子:1帖 | 5回
  • 年度积分:0
  • 历史总积分:15
  • 注册:2007年11月02日
发表于:2008-07-23 22:35:53
6楼
哈哈哈!真的是好帖啊,能用心总结很不容易。希望以后能向你请教!多谢你的文章!!!

可爱的香蕉

  • 精华:0帖
  • 求助:0帖
  • 帖子:1帖 | 6回
  • 年度积分:0
  • 历史总积分:15
  • 注册:2008年5月10日
发表于:2009-03-12 17:49:43
7楼

好贴,支持楼主~~~~~~~~~

quguicai

  • 精华:0帖
  • 求助:0帖
  • 帖子:1帖 | 15回
  • 年度积分:0
  • 历史总积分:16
  • 注册:2010年3月23日
发表于:2010-08-04 08:57:46
8楼
有没有三菱的梯形图算法程序啊

热门招聘
相关主题

官方公众号

智造工程师