HJ212_CRC16校检
代码
def crcFast(text):
"""
hj 212-2017 crc16效验
:param text: 待效验的字符串
:return: result
"""
data = bytearray(text, encoding='utf-8')
crc = 0xffff
dxs = 0xa001
for i in range(len(data)):
hibyte = crc >> 8
crc = hibyte ^ data[i]
for j in range(8):
sbit = crc & 0x0001
crc = crc >> 1
if sbit == 1:
crc ^= dxs
data=str(hex(crc)[2:]).zfill(4)
return data
网上其他版本
def crcFast(text):
"""
hj 212-2017 crc16效验
:param text: 待效验的字符串
:return: result
"""
data = bytearray(text, encoding='utf-8')
crc = 0xffff
dxs = 0xa001
for i in range(len(data)):
hibyte = crc >> 8
crc = hibyte ^ data[i]
for j in range(8):
sbit = crc & 0x0001
crc = crc >> 1
if sbit == 1:
crc ^= dxs
return hex(crc)[2:]
比较
开始我也使用的网上通用的版本,但是当我再运行的时候发现产生了3位的校检码。校检的原始数据如下:
QN=20200828112638954;ST=91;CN=9012;PW=123456;MN=sss;Flage=5;CP=&&ExeRtn=1&&
开始我怀疑我的CRC16生成的是否是错误的。
我找到了HJ212协议的原文
于是,我使用他的源码,看看产生的结果
#include <stdio.h>
int main(void) {
int a;
a=CRC16_Checkout("QN=20200828112638954;ST=91;CN=9012;PW=123456;MN=sss;Flage=5;CP=&&ExeRtn=1&&",75);
printf("%x",a);
return 0;}
int CRC16_Checkout ( char *puchMsg,int usDataLen )
{
unsigned int i,j,crc_reg,check;
crc_reg = 0xFFFF;
for(i=0;i<usDataLen;i++)
{
crc_reg = (crc_reg>>8) ^ puchMsg[i];
for(j=0;j<8;j++)
{
check = crc_reg & 0x0001;
crc_reg >>= 1;
if(check==0x0001)
{
crc_reg ^= 0xA001;
}
}
}
return crc_reg;
}
结果果然不出我所料。
我觉着这里应该在前边补上0的,所以修改了代码。不知道是出协议的人没考虑到还是什么原因,我看了他们C#的代码是有人手动不上的,到底使用哪种代码,看你们自己吧。
C#如下:
public static string GetHj212Crc16(byte[] bytes)
{
int crcRegister = 0xFFFF;
for (int i = 0; i < bytes.Length; i++)
{
crcRegister = (crcRegister >> 8) ^ bytes[i];
for (int j = 0; j < 8; j++)
{
int check = crcRegister & 0x0001;
crcRegister >>= 1;
if (check == 0x0001)
{
crcRegister ^= 0xA001;
}
}
}
string result = string.Format("{0:X}", crcRegister);//转十六进制
for (int i = result.Length; i < 4; i++)//补足 4 位
{
result = "0" + result;
}
return result;
}
地址:C#代码