MODBUS CRC校验原理及C语言实现

来源:互联网 发布:北方工业公司 知乎 编辑:程序博客网 时间:2024/04/30 07:19

MODBUS通信协议的CRC校验原理多项式为8005的逆序A001
01CRC校验原理:
1111111111111111                 初始化CRC寄存机
0000000000000001                
1111111111111110                 异或
                                
0111111111111111 0 LSB0        第一次右位移
                                
0011111111111111 1 LSB1        第二次右位移
1010000000000001//8005反序即A001
1001111111111110                 异或
                                
0100111111111111 0 LSB0        第三次右位移
                                
0010011111111111 1 LSB1        第四次右位移
1010000000000001//8005反序即A001
1000011111111110                 异或
                                
0100001111111111 0 LSB0        第五次右位移
                                
0010000111111111 1 LSB1        第六次右位移
1010000000000001//8005反序即A001
1000000111111110                 异或
                                
0100000011111111 0 LSB0        第七次右位移
                                
0010000001111111 1 LSB1        第八次右#在这里输入你想要说的话题# 位移
1010000000000001//8005反序即A001
1000000001111110                     异或的结果807E
CRC多项式种类很多,采用的方法有逆序、..上面这个是多项式8005的逆序算法。

如果代码为0105则用05继续与结果807E做上面八次位移异或即可。有好的算法共同分享哈。

//========================================================================================

ModBus 通信协议的 CRC ( 冗余循环校验码)含2个字节, 即 16 位二进制数。
CRC 码由发送设备计算, 放置于所发送信息帧的尾部。
接收信息设备再重新计算所接收信息 (除 CRC 之外的部分)的 CRC, 比较CRC 结果


1)预置 1 个 16 位的寄存器为十六进制FFFF(即全为 1) , 称此寄存器为 CRC寄存器。
2) 把第一个 8 位二进制数据 (通信信息帧的第一个字节) 
与 16 位的 CRC寄存器的低 8 位相异或, 把结果放于 CRC寄存器。


3) 把 CRC 寄存器的内容右移一位( 朝低位)用 0 填补最高位, 并检查右移后的移出位。
4) 如果移出位为 0, 重复第 3 步 ( 再次右移一位); 如果移出位为 1, CRC 寄存器与多项式A001 ( 1010 0000 0000 0001) 进行异或。
5) 重复步骤 3 和步骤 4, 直到右移 8 次,这样整个8位数据全部进行了处理。
6) 重复步骤 2 到步骤 5, 进行通信信息帧下一个字节的处理。
7) 计算完成后,得到的16位CRC寄存器的高、低字节进行交换。
8) 最后得到的 CRC寄存器内容即为 CRC码。
Modbus CRC编码的程序代码:
unsigned int CRC16 ( uchar *arr_buff, uchar len)
{
 uint crc=0xFFFF;(1)
 uchar i, j, Data;
 for ( j=0; j
 {
   crc=crc ^*arr_buff++;
   for ( i=0; i<8; i++)
  {
       if( ( crc&0x0001) >0)(2)
       {
           crc=crc>>1;
           crc=crc^ 0xa001;
        }
      else
          crc=crc>>1;(3)   }
 }
return ( crc);
}

//========================================================================================

/*计算CRC码的步骤为:
(1).预置16位寄存器为FFFFH。称此寄存器为CRC寄存器;
(2).把第一个8位数据与CRC寄存器的低位相异或,把结果放于CRC寄存器;
(3).把寄存器的内容右移一位(朝低位),用0填补最高位,检查最低位;
(4).如果最低位为0:重复第3步(再次移位)如果最低位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
(5).重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
(6).重复步骤2到步骤5,进行下一个8位数据的处理;
(7).最后得到的CRC寄存器即为CRC码。(CRC码 = CRC_L +CRC_H)
*/
/*****************crc校验**********************************************/
//crc生成函数,并将crc存储在预先定于的数组中
//调用方式crc16(指向数据的指针,需要校验的数据长度)
unsigned char CRC[2];//定义数组
void crc16(unsigned char *ptr,unsigned int len)
{
unsigned long wcrc=0XFFFF;//预置16位crc寄存器,初值全部为1
unsigned char temp;//定义中间变量
int i=0,j=0;//定义计数
for(i=0;i<len;i++)//循环计算每个数据
{
temp=*ptr&0X00FF;//将八位数据与crc寄存器亦或
ptr++;//指针地址增加,指向下个数据
wcrc^=temp;//将数据存入crc寄存器
for(j=0;j<8;j++)//循环计算数据的
{
if(wcrc&0X0001)//判断右移出的是不是1,如果是1则与多项式进行异或。
{
wcrc>>=1;//先将数据右移一位
wcrc^=0XA001;//与上面的多项式进行异或
}
else//如果不是1,则直接移出
{
wcrc>>=1;//直接移出
}
}
}
temp=wcrc;//crc的值
CRC[0]=wcrc;//crc的低八位
CRC[1]=wcrc>>8;//crc的高八位
}
//===========================================================================================

(1)先选择校验对帧进行除法运算的除数

是二进制比较特串,通常是以多项方式表示,所以CRC又称多项式编码方法,这个多项式也称之为“生成多项式”)。

(2)看所选定的除数二进制位数(k位),

然后在要发送的数据帧(m位)后面加k-1位“0”,(一共是m+k-1位)

以“模2除法”方式除以上面这个除数,

所得到的余数二进制的比特串就是该帧的CRC校验码也称之为FCS(帧校验序列)。

注意,余数的位数一定要比除数只能少一位

(3)再把这个校验码附加在原数据帧后面

最后在接收端再把这个新帧以“模2除法”方式除以前面选择的除数,

如果没有余数,则表明该帧在传输过程中没出错,否则出现了差错。

最高位和最低位必须均为“1”

如在IBM的SDLC(同步数据链路控制)规程中使用的CRC-16(也就是这个除数一共是17位)生成多项式g(x)= x16 + x15 + x2 +1(对应二进制比特串为:1 1000 0000 0000 0101);

而在ISO HDLC(高级数据链路控制)规程、ITU的SDLC、X.25、V.34、V.41、V.42等中使用CCITT-16生成多项式g(x)= x16 + x15 + x5+1(对应二进制比特串为:1 1000 0000 0010 0001)。

“模2除法”与“算术除法”类似,但它既不向上位借位,也不比较除数和被除数的相同位数值的大小,只要以相同位数进行相除即可

模2加法运算为:1+1=0,0+1=1,0+0=0,无进位,也无借位;

模2减法运算为:1-1=0,0-1=1,1-0=1,0-0=0,也无进位,无借位。

相当于二进制中的逻辑异或运算。也就是比较后,两者对应位相同则结果为“0”,不同则结果为“1”。

如100101除以1110,结果得到商为11,余数为1,如图5-9左图所示0

如11×11=101,如图5-9右图所示。

图5-9 “模2除法”和“模2乘法”示例

CRC的生成多项式是P=X3+1代表什么


p(x)=x3+x2+x1+1 对应1111

p(x)=x3+ 1 对应1001