我刚刚写好跟PLC连接测试过,可以的
/
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;
/
/
名称: UART_CRC16_Work()
说明: CRC16校验程序
参数: CRC_Buf:数据地址
CRC_Leni:数据长度
返回: CRC_Sumx:校验值
/
unsigned int UART_CRC16_Work(unsigned char CRC_Buf,unsigned char CRC_Leni)
{
unsigned char i,j;
unsigned int CRC_Sumx;
CRC_Sumx=0xFFFF;
for(i=0;i<CRC_Leni;i++)
{
CRC_Sumx^=(CRC_Buf+i);//异或
for(j=0;j<8;j++)
{
if(CRC_Sumx & 0x01)
{
CRC_Sumx>>=1;
CRC_Sumx^=0xA001;
}
else
{
CRC_Sumx>>=1;
}
}
}
return (CRC_Sumx);
}
CRC校验是循环冗余校验,下面是C#的代码。
protected byte[] GetCRC(byte[] b, int offset, int len)
{
byte CRC16Lo = 0;
byte CRC16Hi = 0;
byte bytC;
byte bytTreat;
byte bytBcrc;
for (int i = 0; i < len; i++)
{
bytC = b[i + offset];
for (int flag = 0; flag <= 7; flag++)
{
bytTreat = (byte)(bytC & 0x80);
bytC = (byte)((bytC 2) % 0x100);
bytBcrc = (byte)(CRC16Hi & 0x80);
CRC16Hi = (byte)(((CRC16Hi 2) % 0x100) + CRC16Lo / 0x80);
CRC16Lo = (byte)((CRC16Lo 2) % 0x100);
if (bytTreat != bytBcrc)
{
CRC16Hi = (byte)(CRC16Hi ^ 0x10);
CRC16Lo = (byte)(CRC16Lo ^ 0x21);
}
}
}
byte[] ReturnData = new byte[2];
ReturnData[0] = CRC16Hi;
ReturnData[1] = CRC16Lo;
return ReturnData;
}
基本原理是:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码也叫(N,K)码。对于一个给定的(N,K)码,可以证明存在一个最高次幂为N-K=R的多项式G(x)。根据G(x)可以生成K位信息的校验码,而G(x)叫做这个CRC码的生成多项式。 校验码的具体生成过程为:假设要发送的信息用多项式C(X)表示,将C(x)左移R位(可表示成C(x)xR),这样C(x)的右边就会空出R位,这就是校验码的位置。用 C(x)xR 除以生成多项式G(x)得到的余数就是校验码。
任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。
以下内容可能对你有用呀。好好看看就明白了。
CRC校验
采用CRC-16,即2字节冗余循环码CRC,低字节在前。CRC码由发端计算,放置于发送消息帧的尾部,接收端再重新计算接收到信息的CRC码,比较计算得到的CRC码是否与接收到的相符,若不符则表明出错。CRC码的计算包括整个消息内容,计算时只用8位数据位,而起始位、停止位及可能的校验位均不参与CRC计算。
CRC校验可以100%检测出所有奇数个随机错误。CRC-16校验可以检测出长度小于等于16的突发错误,可以保证在1014 bit码元中只含有1位未被检测出的错误。CRC-16的具体算法有多种,以下是一个例子。
1置16位寄存器为全1,作为CRC寄存器。
2把一个8位数据与16位CRC寄存器的低字节相异或,把结果放于CRC寄存器中。
3把寄存器的内容右移一位(朝低位),用0填补最高位,检查最低位(移出位)。
4如果最低位为0,重复③(再移位);如果最低位为1,CRC寄存器与多项式A001H(1010 0000 0000 0001)进行异或。
5重复③、④,直到右移8次,这样整个8位数据全部进行了处理。
6重复②-⑤,进行下一个8位数据的处理。
7将一帧的所有数据字节处理完后得到CRC-16寄存器。
8将CRC-16寄存器的低字节和高字节交换,得到的值即为CRC-16码。
1系统先把所有的float转换为double类型运算,最终得到的结果截取前七个作为有效数字,这样做可以使计算结果更准确。
2有效数字:从左边第一个不是0的数字起,到精确到的位数止,所有的数字都叫做这个数的有效数字。比如:124的有效数字就是
1、2、4。024
的有效数字就是
2、4。
3
同样的二进制数,假定你定义有符号(signed)类型,则第一位表示的是正负号,0代表正数,1代表负数;而如果定义无符号型(unsigned)的话,第一位为值了。
4如果用指数表示,float类型有效数字为6~7位。double类型为15~16位,具体跟数字有关。
5这个你是在哪看的啊,不对!
整形常量分为十进制、八进制、十六进制:
八进制形式为012前面有个零,十六进制为0x12前面有个0x(注意x前面是零),
而在一个八进制数字前面加\表示是字符型常量,例如\012为ASCII码为10的字符!
这是我逐字敲上去的,还希望您能采纳!
unsigned int caculate_crc16(unsigned char DAT,unsigned char lenth)
{
//DAT指向要计算CRC的数组,lenth为数据的长度
unsigned int crc=0xffff;//crc的初始值为FFFF;
unsigned char i;
unsigned char j;
for(i=0;i<lenth;i++)
{
crc=crc^DAT[i];
for(j=0;j<8;j++)
{
if(crc&0x01)
{
crc=crc>>1;
crc=crc^0xA001;
}
else
{
crc=crc>>1;
}
}
}
return(crc);
}
unsigned int CZ;
CZ=caculate_crc16(comdata,lenth);
编译成功的
以上就是关于单片机 用c语言编写 modbus rtu 通讯怎么写啊 主要是crc 校验部分不知道怎么写 怎么把一窜字符进行CRC计算全部的内容,包括:单片机 用c语言编写 modbus rtu 通讯怎么写啊 主要是crc 校验部分不知道怎么写 怎么把一窜字符进行CRC计算、易语言CRC16效验程序、CRC16校验码查表法的原理是什么等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)