在工业控制中,Modbus RTU CRC16的校验码用的比较广泛,包括本人富士产品中,PC与伺服电机以及PC与VP系列的变频器的Modbus RTU通讯中都使用到了CRC16.

    而对CRC16的计算的方式基本上有2种:第一种,使用双循环依照CRC的计算方法进行计算,第二种,采用查表的方式。本人愚钝无比,从网络上搜来的查表法都与实际的正确CRC16的结果有所差异,因此编写了一个小程序供自己使用。
   软件的界面很简单,输入诸如“010303020014”的值,然后每2个字符作为一个字节,填入字节数,然后就可以计算出校验码,校验码的多项式为:X16+X15+X2+1.
 
 
实现的源代码如下:
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Edit3: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Memo1: TMemo;
    Label4: TLabel;
  function CalCRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
//××××××××××××××××××××××××××
// CalCRC16用于计算Modbus RTU的CRC16
// 多项式公式为X16+X15+X2+1
//××××××××××××××××××××××××××
function TForm1.CalCRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
const
  GENP=$A001;  //多项式公式X16+X15+X2+1(1100 0000 0000 0101)
var
  crc:Word;
  i:Integer;
  tmp:Byte;
procedure CalOneByte(AByte:Byte);  //计算1个字节的校验码
var
j:Integer;
begin
  crc:=crc xor AByte;   //将数据与CRC寄存器的低8位进行异或
  for j:=0 to 7 do      //对每一位进行校验
  begin
    tmp:=crc and 1;        //取出最低位
    crc:=crc shr 1;        //寄存器向右移一位
    crc:=crc and $7FFF;    //将最高位置0
    if tmp=1 then         //检测移出的位,如果为1,那么与多项式异或
      crc:=crc xor GENP;
      crc:=crc and $FFFF;
  end;
end;
begin
  crc:=$FFFF;             //将余数设定为FFFF
  for i:=AStart to AEnd do   //对每一个字节进行校验
    CalOneByte(AData[i]);
  Result:=crc;
end;
 
 
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Data:array[0..255] of Byte;
  i,j,Count:Integer;
  Res:Word;
  szData:string;
begin
  szData:=Form1.Edit2.Text;    //读入欲校验的字符串
  Count:=StrToInt(form1.Edit3.Text); //读入需要计算的字符串长度
  i:=1;
  j:=0;
  for j:=0 to Count-1 do
  begin
    if (i mod 2)=0 then    //每2个字符放入一个字节中
         i:=i+1;
    if i>=Length(szData) then
        exit;
    Data[j]:=StrToInt('$'+copy(szData,i,2)); //取出字符并转换为16进制数
    i:=i+1;
  end;
 
  Res:=CalCRC16(Data,Low(Data),Count-1);
  form1.Edit1.Text:=IntToHex(Res,4);
end;
 
end.
 
原贴:
http://blog.163.com/shcima@yeah/blog/static/107821988201062105441133/
 
 

你这个程序有问题,有空联系我,不对。我的QQ是992725706

2011-08-21 14:31

cvlsam 回复 dfdfdfdf
已经用于实际项目中了……
2015-05-07 11:09

15751010184 回复 dfdfdfdf
不要怀疑这个程序的正确性。。。。不过modbus上使用可能是需要把高低对调一下,别的我就不知道了!

  Res:=CalCRC16(Data,Low(Data),Count-1);
  crc:=IntToHex(Res,4);
  crcL:=crc[3]+crc[4] ;
  crcH:=crc[1]+crc[2] ;
  memo1.Text:=crcL+crcH;
2015-05-07 11:04

不过在modbus通讯字符串里,那个得到的校验码确实需要把高位和低位对调一下。。。但是任然万分感激楼主把我从一个星期的蛋疼中解救出来。。。。楼主我能加你qq么?以后多请教一下你。。。。
2015-05-07 11:00

真是感激啊。。。。。。位校验程序网上很多,关键就在需要校验的字符怎么处理再给予校验,各种坑啊。。。。楼主贴出了字符到校验的处理全过程。。。。。业界良心啊!!!!!!!!
2014-02-20 23:03

1
您太厉害了 好佩服
2013-07-21 17:41

patchhome

好像计算出来的高2位和低2位应该对调才和设备的对上。

2011-05-16 08:40

2010-09-19 10:50

恩,我也才刚冲学校走出来, 单位要求学习delphi,先在编城中有关通讯这块遇到问题,主要用modbus协议CRC的算法,有空向您多请教
 
 
 
 
 
 
 
 
 
 

如何使用Delphi编写Modbus RTU CRC16的校验码的更多相关文章

  1. C语言实现的CRC16/CCITT-FALSE校验码函数

    要求:输入字符串“00 AA FF CC AA 01 00” 得到校验码“79B1” 方法1: // ConsoleApplication1.cpp: 定义控制台应用程序的入口点. // #inclu ...

  2. Delphi Modbus RTU CRC16校验码

    function CheckCrc16(const ABuf; ALen: Integer): Boolean;var uwTemp: WORD; i, j: BYTE; P: PByte;begin ...

  3. Modbus RTU通信协议详解以及与Modbus TCP通信协议之间的区别和联系

    Modbus通信协议由Modicon公司(现已经为施耐德公司并购,成为其旗下的子品牌)于1979年发明的,是全球最早用于工业现场的总线规约.由于其免费公开发行,使用该协议的厂家无需缴纳任何费用,Mod ...

  4. PHP CRC16 校验码的算法怎么使用

    PHP CRC16 校验码的算法如何使用最近用到CRC16, 我现在就是要把 010301180001 算出CRC16的校验码,通过其他工具,可以得到 校验码是 05F1 最后完整的代码就是 0103 ...

  5. CRC16冗余循环检测计算器-好用。modbus RTU

    开始使用 http://cht.nahua.com.tw/index.php?url=http://cht.nahua.com.tw/software/crc16/&key=Modbus,%2 ...

  6. Modbus协议栈实现Modbus RTU多主站支持

    前面我们已经详细讲解过Modbus协议栈的开发过程,并且利用协议栈封装了Modbus RTU主站和从站,Modbus TCP服务器与客户端,Modbus ASCII主站与从站应用.但在使用过程中,我们 ...

  7. C# 开发Modbus Rtu客户端 modbus测试Demo,Modbus 串口通信 , 虚拟MODBUS-RTU测试

    前言 本文将使用一个NuGet公开的组件技术来实现一个ModBus RTU的客户端,方便的对Modbus rtu的服务器进行读写,这个服务器可以是电脑端C#设计的,也可以是PLC实现的,也可以是其他任 ...

  8. modbus ASCII和MODBUS RTU区别

    下表是MODBUS ASCII协议和RTU协议的比较: 协议 开始标记 结束标记 校验 传输效率 程序处理 ASCII :(冒号) CR,LF LRC 低 直观,简单,易调试 RTU 无 无 CRC ...

  9. Modbus RTU程序开发解读

    Modbus是很好的串口通信协议,其中RTU协议最为常用,通过Modbus RTU,我们可以轻松读写串口信息. 从官网下载libModbus,观察modbus.h可知关键的结构体为: typedef ...

随机推荐

  1. Alpha 冲刺

    队名:我头发呢队 组长博客 作业博客 杰(组长) 过去两天完成了哪些任务 查阅Python爬取音源的资料,如 Python3爬虫抓取网易云音乐热评实战 Python爬取高品质QQ音乐(2) 如何爬网易 ...

  2. Linq学习(一)

    与LINQ有关的语言特性 1.隐式类型 var 2.匿名类型 如:var obj = new {Guid.Empty, myTitle = "匿名类型", myOtherParam ...

  3. 【CDN】- 什么是CDN

    高冷科普: CDN,Content Delivery Network缩写,即内容分发网络.通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量 ...

  4. linux perf: 为什么采样频率设置成99Hz而不是100Hz

    早晨在linuxer看到文章,感觉挺有意思,最早研究perf的时候接触过这些概念,乍一看倍感亲切. sudo perf record -F  99 -a -g --sleep 20 perf reco ...

  5. 【bzoj3325】[Scoi2013]密码 逆模拟Manacher

    题目描述 给出一个只包含小写字母的字符串的长度.以每一个字符为中心的最长回文串长度.以及以每两个相邻字符的间隙为中心的最长回文串长度,求满足条件的字典序最小的字符串. 输入 输入由三行组成.第一行仅含 ...

  6. linux系统——ld-linux.so.X查找和加载共享动态库的顺序

    ld-linux.so查找共享库的顺序: Glibc安装的库中有一个为ld-linux.so.X,其中X为一个数字,在不同的平台上名字也会不同.可以用ldd查看: #ldd /bin/cat linu ...

  7. python代理池的实现

    https://github.com/wangqifan/ProxyPool http://python.jobbole.com/86994/

  8. String中的“equal方法”和“==”

    二话不说,先来说下重写的事情: 在Java中,String .Math.还有Integer.Double....等这些封装类重写了Object中的equals()方法,让它不再比较其对象在内存中的地址 ...

  9. 什么是SetUID

    1. 什么是SetUID 我们知道,在linux的命令行下执行“ps”命令时,就会列出当前系统中的所有进程,在其中可以看到每个进程都和用户的真实id关联,实际上,Linux中的每个进程还跟一个称为有效 ...

  10. HDU 1841 Find the Shortest Common Superstring----KMP

    题意:给两个字符串,问包含这两个字符串的最小的字符串的长度 kmp返回匹配串长度 #include "iostream" #include<cstdio> #inclu ...