modbus协议CRC校验计算方式?该怎么计算?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了modbus协议CRC校验计算方式?该怎么计算?相关的知识,希望对你有一定的参考价值。
例如我要往一个串口发送
01 03 00 01 00 08 ,他的校验15 CC是怎么计算来的?找了不少资料,来来去去就那么一两句话,什么或运算,冗余的,看的懵懵懂懂,希望有一个详细的解释,步骤清楚一点的,(能多清楚就多清楚吧)如果可以,最好希望有注解的C++语言代码,满意可加分!
1、加载一值为0XFFFF的16位寄存器,此寄存器为CRC寄存器。
2、把第一个8位二进制数据(即通讯信息帧的第一个字节)与16位的CRC寄存器的相异或,异或的结果仍存放于该CRC寄存器中。
3、把CRC寄存器的内容右移一位,用0填补最高位,并检测移出位是0还是1。
4、如果移出位为零,则重复第三步(再次右移一位);如果移出位为1,CRC寄存器与0XA001进行异或。
5、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理。
6、重复步骤2和5,进行通讯信息帧下一个字节的处理。
7、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换
8、最后得到的CRC寄存器内容即为:CRC校验码。 参考技术B 执行八次之后就不再执行移位操作了。追问
请问有相关的C语言或者C++语言的代码么?那样我好理解些,简单的一句话,我没弄太懂!
参考技术C 不用知道怎么来 会计算就可以了 下载一个计算软件追问我就是有些这样的偏执,想知道所以然!根据C语言代码和别人说的解释,感觉完全不对头!好困惑!
追答循环冗余校验(CRC)生成步骤比较复杂 貌似要根据前面的数据位串生成多项式 然后用前面的数据位串除以多项式的系数生成的数据位 所得的余数不满16的添0
参考技术D 生成 CRC 的过程为:1. 将一个 16 位寄存器(称作 CRC 寄存器)初始赋值为十六进制 FFFF (全 1);
2. 将报文的第一个字节( 8位)与 16 位 CRC 寄存器的低字节异或,结果置于 CRC 寄存器;
3. 将 CRC 寄存器右移 1位 (向 LSB 方向), MSB 充零,并检测 LSB:
4. (如果 LSB 为 0): 重复步骤 3 (另一次移位).
(如果 LSB 为 1): 对 CRC 寄存器异或多项式值 0xA001 (1010 0000 0000 0001).
5. 重复步骤 3 和 4,直到完成 8 次移位操作后,一个字节的处理完毕。
6. 对报文中的下一个字节重复步骤 2 到 5继续此操作,直至所有报文被处理完毕。
7. CRC 寄存器中的最终值为 CRC 值.
8. 当放置 CRC 值于报文时,注意高低字节必须交换。追问
先拿01与11111111 11111111的前八个1异或,得到结果1111111011111111,然后这里是先移位,再检测执行第4步码?我右移一位,得到结果0111111101111111,此时LSB为1,异或0xA001,得到11011111 01111110,这算执行一次移位操作,再执行到移位七次,得到0110 0000 0011 1110,此时需要检测LSB为0,并对它再一次移位么?还是执行第八次移位后,就不判断LSB是否为零执行后续操作了?
还有就是高低位还弄不懂
你的理解有问题,首先要明白MSB是指bit15,LSB是指bit0;高字节是指bit15~bit8,低字节是指bit7~bit0。01若是报文第一个字节值(16进制,其2进制是00000001),那么:
第2步,01H与11111111 11111111的低字节异或,结果是11111111 11111110。
第3步,右移一位就成为01111111 11111111,检测的LSB原意是右移出来的位(即右移之前的LSB)。
第4步,判断LSB=0就直接返回第3步;LSB=1则把CRC寄存器与多项式值 0xA001异或,再返回第3步。
第5步,由于01H有8个bit,所以必须进行8 次”右移-判断是否要异或“操作,一个字节的处理才完毕。
第6步,按照第2~5步的操作处理第2个、第3个......字节,直至所有的报文字节被处理完毕。
字数太多了,只好截图了!
第一次的是引用资料,先右移再检测(移出的)LSB。
第二次说的也没错,先右移再检测右移之前的LSB,其实与第一次操作是一样的。
请注意:原资料的描述不够准确,因为右移出来的位不能再称为LSB。我加上括号的3个字就清楚了。
modbus+rtu功能码是啥进制数
参考技术A 其实任何数制都是一回事,大多协议相关资料在解释协议的时候,多采用十六进制表达MODBUS协议码,但这只是一种习惯而已,十进制表达也没有错的,只是大家不这样表达而已。无论什么协议数据,在进行信道上进行传输时都是以二进制码串的方式进行的。 参考技术B 在工业控制中,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.
以上是关于modbus协议CRC校验计算方式?该怎么计算?的主要内容,如果未能解决你的问题,请参考以下文章