Swift-CRC16modbus校验算法
CRC介绍:
循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC。它是利用除法及余数的原理来作错误侦测(Error Detecting)的。实际应用时,发送装置计算出CRC值并随数据一同发送给接收装置,接收装置对收到的数据重新计算CRC并与收到的CRC相比较,若两个CRC值不同,则说明数据通讯出现错误。
CRC-16:
CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器与8-bit的数据进行异或,之后对CRC寄存器从高到低进行移位,在最高位的位置补零,而最低位如果为1,则把寄存器与预定义的多项式码进行异或,否则如果LSB为零,则无需进行异或。重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。所有的字符处理完成后CRC寄存器内的值即为最终的CRC值;其中CRC16种最常用的为modbus参数模型(校验码的计算多项式为X16 + X15 + X2 + 1)
具体做法:
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寄存器内容即为:CRC16校验码。
C语言写法
//C语言计算CRC16
unsigned short do_crc(unsigned char *ptr, int len)
{
unsigned int i;
unsigned short crc = 0xFFFF;
while(len--)
{
crc ^= *ptr++;
for (i = 0; i < 8; ++i)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
return crc;
}
Swift语言写法
class CRC16{
static let instance = CRC16()
func getCRCResult (data: [UInt8]) -> [UInt8] {
var crc = getCRC(arr: data)
var crcArr: [UInt8] = [0,0]
for i in (0..<2).reversed() {
crcArr[i] = UInt8(crc % 256)
crc >>= 8
}
return crcArr
}
private func getCRC(arr:[UInt8]) -> Int{
var CRC:Int = 0xffff
let POLYNOMIAL:Int = 0xa001
let length = arr.count
for i in 0..<length{
CRC ^= Int(arr[i])
for j in 0..<8{
if((CRC & 0x0001) != 0){
CRC >>= 1
CRC ^= POLYNOMIAL
}else{
CRC >>= 1
}
}
}
return CRC
}
}
ps:该CRC16校验算法为平时常用算法,以供大家参考选择