Mudbus协议CRC校验码C#
- 什么是modbus
- 协议特点
- 协议格式
- modbus-crc16校验原理方法
- 帧校验
- CRC计算方法:
- 例子
- C#代码
- Demo源码下载
什么是modbus
Modbus是一种串行通信协议,最初由Modicon(目前属于施耐德电气公司)于1979年开发
Modbus协议是应用在Modicon产品上的,后来才被移植到其他产品上
Modbus协议的通信接口可以有多种选择,如RS232、RS485、以太网等
协议特点
支持主从方式,即主站、从站
Modbus协议主要分为两种格式,即Modbus RTU和Modbus ASCII,Modbus RTU使用二进制格 式传输数据,而Modbus ASCII则将数据以ASCII码形式进行传输。此外,Modbus还可以通过TCP/IP协议进行网络通信,称为Modbus TCP/IP。
协议格式
- 起始地址(也就是常说的站号)
- 功能码 (01,03,06,10,16等等)
- 数据内容
- 校验码(CRC16校验)
modbus-crc16校验原理方法
帧校验
在ModbusRTU和Modbus ASCII多数用的是帧校验,帧校验有两种,一种是ModbusRTU采用的CRC(循环冗余校验),另一种是Modbus ASCII采用的LRC( 纵向冗余校验),这两种校验方式具体内容我们不再赘述,现在主要谈ModbusRTU通信协议的CRC校验的具体实现代码。ModbusRTU通讯数据(信息帧)的格式为:从站地址码(1byte)+功能码(1byte)+数据区(N bytes)+CRC校验码(2 bytes)。CRC寄存器为16位,它是经过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寄存器的高、低字节进行交换;
例子
//下面是5行示例crc16数据,前6个字节数据,后两个字节crc结果。
//F9 0C C2 36 13 2A 55 2A
// F9 0C C2 35 13 32 A5 20
//F9 0C C2 61 13 3A E5 36
//F9 0C C2 62 13 02 14 E4
// F9 0C C2 39 13 0A 64 F1
C#代码
/// <summary>
/// CRC校验,参数data为byte数组
/// 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寄存器的高、低字节进行交换;
//下面是5行示例crc16数据,前6个字节数据,后两个字节crc结果。
//F9 0C C2 36 13 2A 55 2A
// F9 0C C2 35 13 32 A5 20
//F9 0C C2 61 13 3A E5 36
//F9 0C C2 62 13 02 14 E4
// F9 0C C2 39 13 0A 64 F1
/// </summary>
/// <param name="data">校验数据,字节数组</param>
/// <returns>字节0是高8位,字节1是低8位</returns>
public static byte[] CRCCalc(byte[] data)
{
//1.预置1个16位的寄存器为十六进制FFFF(即全为1); 称此寄存器为CRC寄存器;
//crc计算赋初始值
var crc = 0xffff;
for (var i = 0; i < data.Length; i++)
{
//2.把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器;
crc = crc ^ data[i]; //将八位数据与crc寄存器异或 ,异或的算法就是,两个二进制数的每一位进行比较,如果相同则为0,不同则为1
//3.把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位;
//4.如果移出位为0:重复第3步(再次右移一位); 如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
//5.重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
for (var j = 0; j < 8; j++)
{
int temp;
temp = crc & 1;
crc = crc >> 1;
crc = crc & 0x7fff;
if (temp == 1) crc = crc ^ 0xa001;
crc = crc & 0xffff;
}
}
//CRC寄存器的高低位进行互换
var crc16 = new byte[2];
//CRC寄存器的高8位变成低8位,
crc16[1] = (byte)((crc >> 8) & 0xff);
//CRC寄存器的低8位变成高8位
crc16[0] = (byte)(crc & 0xff);
return crc16;
}
Demo源码下载
Mudbus协议CRC校验码C#Demo