MODBUS CRC校验原理及C语言实现
来源:互联网 发布:北方工业公司 知乎 编辑:程序博客网 时间:2024/04/30 07:19
MODBUS通信协议的CRC校验原理多项式为8005的逆序A001
列01的CRC校验原理:
1111111111111111 初始化CRC寄存机
0000000000000001
1111111111111110 异或
0111111111111111 0 LSB为0 第一次右位移
0011111111111111 1 LSB为1 第二次右位移
1010000000000001//8005反序即A001
1001111111111110 异或
0100111111111111 0 LSB为0 第三次右位移
0010011111111111 1 LSB为1 第四次右位移
1010000000000001//8005反序即A001
1000011111111110 异或
0100001111111111 0 LSB为0 第五次右位移
0010000111111111 1 LSB为1 第六次右位移
1010000000000001//8005反序即A001
1000000111111110 异或
0100000011111111 0 LSB为0 第七次右位移
0010000001111111 1 LSB为1 第八次右#在这里输入你想要说的话题# 位移
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
- MODBUS CRC校验原理及C语言实现
- CRC校验C语言实现
- CRC校验C语言实现
- CRC算法原理及C语言实现
- CRC算法原理及C语言实现
- CRC算法原理及C语言实现
- 关于CRC冗余校验原理及实现
- C语言实现CRC校验数据
- CRC冗余校验的C语言实现
- c语言实现CRC校验和
- 用C语言实现CRC校验
- c语言CRC校验
- CRC校验算法及实现 C
- CRC算法原理及C语言实现(一)
- CRC算法原理及C语言实现(转)
- CRC校验C实现
- modbus crc校验
- modbus协议crc校验
- 大小写字母的转换
- python基础与基本数据类型
- netty使用入门
- Unity3D学习之路
- Qt error Link 2019无法解析外部符号
- MODBUS CRC校验原理及C语言实现
- 《不要急于开发要善于思考》---做个记录而已
- 深度学习博客汇总
- spring boot学习笔记
- c++的隐式类型转换
- 正则表达式
- EZ-USB® 技术参考手册
- C++之基础知识学习笔记
- 设计模式六大原则例子(六)-- 开放封闭原则(OCP)例子