CRC16校验使用体验

CRC16校验

最近开发有用到CRC16校验,但是网上普遍是CRC-16/MODBUS的,项目上使用的是CRC-16/X25,只有MODBUS例子可以参考,但是对其中几个参数以及这两种算法有什么区别不是很明白,因此查找了关于crc16的相关内容,之后终于明白了其中一个关键的参数,特此做下记录。用了网上代码的直接生成法

感谢该网友上传的js的crc16校验代码
http://download.csdn.net/download/oukunqing/9553070#comment

crc16检验 C#
https://www.cnblogs.com/oukunqing/p/5820640.html

crc16在线检验工具
http://www.ip33.com/crc.html
里面有完整的各种多项式版本的校验算法,以及各个之间的区别
小程序中js的CRC=代码如下

 

var CRC = {};

CRC.CRC16 = function (data) {
var len = data.length;
if (len > 0) {
var crc = 0xFFFF;      //初始值

for (var i = 0; i < len; i++) {
crc = (crc ^ (data[i]));
for (var j = 0; j < 8; j++) {
crc = (crc & 1) != 0 ? ((crc >> 1) ^ 0x8408) : (crc >> 1);     //0x8408 由来见代码结尾
}
}
crc = crc ^ 0xFFFF       //结果异或
var hi = ((crc & 0xFF00) >> 8); //高位置
var lo = (crc & 0x00FF); //低位置

return [hi, lo];
}
return [0, 0];
};

CRC.isArray = function (arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
};

CRC.ToCRC16 = function (str, isReverse) {
return CRC.toString(CRC.CRC16(CRC.isArray(str) ? str : CRC.strToByte(str)), isReverse);
};

CRC.ToModbusCRC16 = function (str, isReverse) {
return CRC.toString(CRC.CRC16(CRC.isArray(str) ? str : CRC.strToHex(str)), isReverse);
};

CRC.strToByte = function (str) {
var tmp = str.split(''), arr = [];
for (var i = 0, c = tmp.length; i < c; i++) {
var j = encodeURI(tmp[i]);
if (j.length == 1) {
arr.push(j.charCodeAt());
} else {
var b = j.split('%');
for (var m = 1; m < b.length; m++) {
arr.push(parseInt('0x' + b[m]));
}
}
}
return arr;
};

CRC.convertChinese = function (str) {
var tmp = str.split(''), arr = [];
for (var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s <= 0 || s >= 127) {
arr.push(s.toString(16));
}
else {
arr.push(tmp[i]);
}
}
return arr;
};

CRC.filterChinese = function (str) {
var tmp = str.split(''), arr = [];
for (var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s > 0 && s < 127) {
arr.push(tmp[i]);
}
}
return arr;
};

CRC.strToHex = function (hex, isFilterChinese) {
hex = isFilterChinese ? CRC.filterChinese(hex).join('') : CRC.convertChinese(hex).join('');

//清除所有空格
hex = hex.replace(/\s/g, "");
//若字符个数为奇数,补一个空格
hex += hex.length % 2 != 0 ? " " : "";

var c = hex.length / 2, arr = [];
for (var i = 0; i < c; i++) {
arr.push(parseInt(hex.substr(i * 2, 2), 16));
}
return arr;
};

CRC.padLeft = function (s, w, pc) {
if (pc == undefined) {
pc = '0';
}
for (var i = 0, c = w - s.length; i < c; i++) {
s = pc + s;
}
return s;
};

CRC.toString = function (arr, isReverse) {
if (typeof isReverse == 'undefined') {
isReverse = true;
}
var hi = arr[0], lo = arr[1];
return CRC.padLeft((isReverse ? hi + lo * 0x100 : hi * 0x100 + lo).toString(16).toUpperCase(), 4, '0');
};




C# CRC 代码如下

   public static byte[] CRC1625(byte[] dataBytes)
        {
            string str = "";
            int len = dataBytes.Length;
            if (len > 0)
            {
                var crc = 0xffff;   //①
                for (int i = 0; i < len; i++)
                {
                    crc = (crc ^ (dataBytes[i]));
                    for (int j = 0; j < 8; j++)
                    {
                        crc = (crc & 1) != 0 ? ((crc >> 1) ^ 0x8408) : (crc >> 1);   //②
                    }
                }
                crc = crc ^ 0xffff;   //③
                var hi = ((crc & 0xFF00) >> 8);
                var lo = ((crc & 0x00ff));
                str = hi.ToString("X2") + lo.ToString("X2");

            }
            return Encoding.UTF8.GetBytes(str);
        }

说明
① 根据 crc16在线检验工具 获得初始值

② CRC-16/X25算法 多项式x16+x12+x5+1 (表示第16位12位5位第0位位1,位从0起) 即0001 0001 0000 0010 0001 去掉高位0001 后转换十六进制为1021
1021即为多项式简写
同时对转换成二进制的多项式去高位并反转得到 1000 0100 0000 1000 转换成十六进制为 8408

CRC-16/USB算法 x16+x15+x2+1 表示第16位15位2位第0位位1,位从0起) 即0001 1000 0000 0000 0101 去掉高位0001 后转换十六进制为8005
8005即为多项式简写
同时对转换成二进制的多项式去高位并反转得到 1010 0000 0000 0001转换成十六进制为 A001

③根据 crc16在线检验工具 获得结果异或值

你可能感兴趣的:(js,C#)