前言 这一节说明一下数据传输中常用的CRC校验 所谓CRC校验,说白了就是对数据做下计算,然后把计算结果放到最后面 平时用的最多的算是CRC16 直接上菜计算CRC /**
* @brief calculate CRC
* @param *modbusdata: Source data address
* @param length: data length
* @param
* @retval CRC16 Value
* @example
**/
int crc16_modbus(u8 *modbusdata, int length)
{
int i, j;
int crc = 0xffff;//0xffff or 0
for (i = 0; i < length; i++)
{
crc ^= modbusdata;
for (j = 0; j < 8; j++)
{
if ((crc & 0x01) == 1)
{
crc = (crc >> 1) ^ 0xa001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
判断接收的数据CRC是否正确 /**
* @brief check CRC for data
* @param *modbusdata: Read data address
* @param length: Read data length
* @param
* @retval 1:CRC16 OK
* @example
**/
int crc16_flage(u8 *modbusdata, int length)
{
int Receive_CRC=0,calculation=0; if(length<=2)
{
return 0;
} Receive_CRC = crc16_modbus(modbusdata, length-2);
calculation = modbusdata[length-2];
calculation <<= 8;
calculation += modbusdata[length-1];
if(calculation != Receive_CRC)
{
return 0;
}
return 1;
}
发送的数据加上CRC 我想发送 01 00 55 aa 数据 最终发送的数据 说明: 1.最后两位 F7 和 BE就是经过CRC16计算之后的数据;高位在前,低位在后 2.整个数据发给另一个设备以后,另一个设备用同样的方式计算 01 00 55 aa 的CRC16值 然后判断下自己计算的值是不是 F7,BE
判断接收的数据CRC是否正确
上位机(C# / JAVA)CRC16校验程序 ///
/// calculate CRC
///
/// Source data address
/// data length
///
private int crc16_modbus(byte[] modbusdata, int length)
{
int i, j;
int crc = 0xffff; //0xffff or 0
try
{
for (i = 0; i < length; i++)
{
crc ^= modbusdata&0xff;
for (j = 0; j < 8; j++)
{
if ((crc & 0x01) == 1)
{
crc = (crc >> 1) ^ 0xa001;
}
else
{
crc >>= 1;
}
}
}
}
catch (Exception)
{
throw;
}
return crc;
}
///
///
///
///
///
///
private int crc16_flage(byte[] modbusdata, int length)
{
int Receive_CRC = 0, calculation = 0;//接收到的CRC,计算的CRC
if(length<=2) return 0;
Receive_CRC = crc16_modbus(modbusdata, length-2);
calculation = modbusdata[length -2];
calculation <<= 8;
calculation += modbusdata[length-1];
if (calculation != Receive_CRC)
{
return 0;
}
return 1;
}
注:对于上位机byte类型需要&0xff 扩展 大部分设备的CRC16计算方式,这个地方是 0xffff, 但是也有0的情况
|