CRC-16 (Modbus)校验码
2017-12-04 17:21
771 查看
CRC16_MODBUS:多项式x16+x15+x5+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0x0000异或。
参考学习网址:
1.CRC16常见几个标准的算法及C语言实现 - CSDN博客 http://blog.csdn.net/leumber/article/details/54311811
2.Java生成CRC16数据校验码 - 专注于大数据技术研究和应用 - CSDN博客 http://blog.csdn.net/fjssharpsword/article/details/53884915
3.Java CRC16校验 - CSDN博客 http://blog.csdn.net/trbbadboy/article/details/42145461/
具体代码:
参考学习网址:
1.CRC16常见几个标准的算法及C语言实现 - CSDN博客 http://blog.csdn.net/leumber/article/details/54311811
2.Java生成CRC16数据校验码 - 专注于大数据技术研究和应用 - CSDN博客 http://blog.csdn.net/fjssharpsword/article/details/53884915
3.Java CRC16校验 - CSDN博客 http://blog.csdn.net/trbbadboy/article/details/42145461/
具体代码:
使用
//"7E000560313233" (hex) ---> CRC-16 (Modbus) 0xBD53 String str16jinzhi = "7E000560313233"; byte[] str16jinzhiTobyte = CrcheckUtil.hexStringToBytes(str16jinzhi); String crc16str = Make_CRC(str16jinzhiTobyte); Log.d("ActImageList", "任意byte[] 计算得 crc16校验码:" + crc16str);//两个低位在前,两个高位在后 Log.d("ActImageList", "=================CRC-16 (Modbus)====================="); int crc = CrcheckUtil.calcCrc16(str16jinzhiTobyte); String str10to16 = String.format("0x%04x", crc);//10进制转换16正确 Log.d("ActImageList", "十进制数 crc16 转16进制:" + str10to16); Log.d("ActImageList", "===================CRC-16 (Modbus)==================="); int result = CrcheckUtil.getCrc16(str16jinzhi); Log.d("ActImageList", "计算得到十进制数crc校验码:" + result); String result10to16 = String.format("0x%04x", result); Log.d("ActImageList", "十进制数crc校验码 转16进制:" + result10to16);
/** * CRC-16 (Modbus) : * 计算产生校验码 * @param data 需要校验的数据 * @return 校验码 */ public static String Make_CRC(byte[] data) { byte[] buf = new byte[data.length];// 存储需要产生校验码的数据 for (int i = 0; i < data.length; i++) { buf[i] = data[i]; } int len = buf.length; int crc = 0xFFFF;//16位 for (int pos = 0; pos < len; pos++) { if (buf[pos] < 0) { crc ^= (int) buf[pos] + 256; // XOR byte into least sig. byte of // crc } else { crc ^= (int) buf[pos]; // XOR byte into least sig. byte of crc } for (int i = 8; i != 0; i--) { // Loop over each bit if ((crc & 0x0001) != 0) { // If the LSB is set crc >>= 1; // Shift right and XOR 0xA001 crc ^= 0xA001; } else // Else LSB is not set crc >>= 1; // Just shift right } } String c = Integer.toHexString(crc); if (c.length() == 4) { c = c.substring(2, 4) + c.substring(0, 2); } else if (c.length() == 3) { c = "0" + c; c = c.substring(2, 4) + c.substring(0, 2); } else if (c.length() == 2) { c = "0" + c.substring(1, 2) + "0" + c.substring(0, 1); } return c; }
工具类
public class CrcheckUtil { private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; private static final int POLYNOMIAL = /*0xA053;*//*0x0589*/0xA001; /* 02 05 00 03 FF 00 的不同crc计算值: CRC-16 0x127C CRC-16 (Modbus) 0x097C 对应的多项式为 0xA001 CRC-16 (Sick) 0xE2F0 CRC-CCITT (XModem) 0xF2B8 CRC-CCITT (0xFFFF) 0xFCA8 CRC-CCITT (0x1D0F) 0xC386 CRC-CCITT (Kermit) 0xA63E CRC-DNP 0x6E28*/ private static final int PRESET_VALUE = 0xFFFF; public static String getHexString(int i){ String hexString = String.format("%04x",i); return hexString; } /** * @param data byte[] * @return 低位在前,高位在后的16进制字符串 */ public static String getCrc16String(byte[] data){ StringBuilder builder = new StringBuilder(); String hex = getHexString(getCrc16(data)); builder.append(hex.substring(2)); builder.append(hex.substring(0,2)); return builder.toString(); } /** * @param data String * @return 低位在前,高位在后的16进制字符串 */ public static String getCrc16String(String data){ StringBuilder builder = new StringBuilder(); String hex = getHexString(getCrc16(data)); builder.append(hex.substring(2)); builder.append(hex.substring(0,2)); return builder.toString(); } /** * @param data byte数组 * @return CRC16校验得到的十进制int */ public static int getCrc16(byte[] data){ System.out.println("\nCRC 16 calculation progress:\n"); int current_crc_value = PRESET_VALUE; for (int i = 0; i < data.length; i++){ current_crc_value ^= data[i] & 0xFF; for (int j = 0; j < 8; j++ ) { if ((current_crc_value & 1) != 0) { current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL; } else{ current_crc_value = current_crc_value >>> 1; } } } return current_crc_value & 0xFFFF; } /** * @param str 16进制字符串 * @return CRC16校验得到的十进制int */ public static int getCrc16(String str){ byte[] data = hexStringToBytes(str); System.out.println("\nCRC 16 calculation progress:\n"); int current_crc_value = PRESET_VALUE; for (int i = 0; i < data.length; i++){ current_crc_value ^= data[i] & 0xFF; for (int j = 0; j < 8; j++ ) { if ((current_crc_value & 1) != 0) { current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL; } else{ current_crc_value = current_crc_value >>> 1; } } } return current_crc_value & 0xFFFF; } /** * byte[] 转 16进制字符 * * @param b * @return */ public static String printHexString(byte[] b) { StringBuffer returnValue = new StringBuffer(); for (int i = 0; i < b.length; i++) { String hex = Integer.toHexString(b[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } if (i % 2 == 0) { returnValue.append(hex.toUpperCase() + ""); } else { returnValue.append(hex.toUpperCase() + " "); } } return returnValue.toString(); } /** * 方法一: * byte[] to hex string * * @param bytes * @return */ public static String bytesToHexFun1(byte[] bytes) { // 一个byte为8位,可用两个十六进制位标识 char[] buf = new char[bytes.length * 2]; int a = 0; int index = 0; for(byte b : bytes) { // 使用除与取余进行转换 if(b < 0) { a = 256 + b; } else { a = b; } buf[index++] = HEX_CHAR[a / 16]; buf[index++] = HEX_CHAR[a % 16]; } return new String(buf); } /** * 方法二: * byte[] to hex string * * @param bytes * @return */ public static String bytesToHexFun2(byte[] bytes) { char[] buf = new char[bytes.length * 2]; int index = 0; for(byte b : bytes) { // 利用位运算进行转换,可以看作方法一的变种 buf[index++] = HEX_CHAR[b >>> 4 & 0xf]; buf[index++] = HEX_CHAR[b & 0xf]; } return new String(buf); } /** * byte[]转换成16进制字符串 * * @param src * @return */ public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } /** * @param b * 字节数组 * @return 16进制字符串 * @throws */ public static String bytes2HexString(byte[] b) { StringBuffer result = new StringBuffer(); String hex; for (int i = 0; i < b.length; i++) { hex = Integer.toHexString(b[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } result.append(hex.toUpperCase()); } return result.toString(); } /** * 16进制字符串转byte[] * * @param hexString * @return */ public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } static byte[] crc16_tab_h = { (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40 }; static byte[] crc16_tab_l = { (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12, (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7, (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74, (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98, (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D, (byte) 0x4C, (byte) 0x8C, (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40 }; /** * 计算CRC16校验 * * @param data * 需要计算的数组 * @return CRC16校验值 */ public static int calcCrc16(byte[] data) { return calcCrc16(data, 0, data.length); } /** * 计算CRC16校验 * * @param data * 需要计算的数组 * @param offset * 起始位置 * @param len * 长度 * @return CRC16校验值 */ public static int calcCrc16(byte[] data, int offset, int len) { return calcCrc16(data, offset, len, 0xffff); } /** * 计算CRC16校验 * * @param data * 需要计算的数组 * @param offset * 起始位置 * @param len * 长度 * @param preval * 之前的校验值 * @return CRC16校验值 */ public static int calcCrc16(byte[] data, int offset, int len, int preval) { int ucCRCHi = (preval & 0xff00) >> 8; int ucCRCLo = preval & 0x00ff; int iIndex; for (int i = 0; i < len; ++i) { iIndex = (ucCRCLo ^ data[offset + i]) & 0x00ff; ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex]; ucCRCHi = crc16_tab_l[iIndex]; } return ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff; } }
相关文章推荐
- CRC16算法之三:CRC16-CCITT-MODBUS算法的java实现
- CRC-16/MODBUS 校验位计算
- CRC-16 (Modbus)
- 计算ModBus CRC 校验码(delphi实现)
- CRC代码算法实现-CRC-16 MODBUS代码实验
- C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)
- Modbus CRC-16
- CRC-16/MODBUS
- C#:循环冗余校验CRC-16-CCITT和CRC-32-IEEE 802.3
- crc16 程序
- 最详细易懂的CRC-16校验原理(附源程序)
- 信息深圳网-CRC16在线校验工具-生成多项式x16+x12+x5+1(0x11021) 介绍
- 最详细易懂的CRC-16校验原理(附源…
- C#,Java,C -循环冗余检验:CRC-16-CCITT查表法
- LabView在MODBUS规约CRC实现以及通讯技术
- CRC-16标准校验算法
- MOdBUS RTU 下计算校验码的代码
- CRC16常见几个标准的算法及C语言实现
- 常用校验码(奇偶校验,海明校验,CRC)学习总结
- 安卓能用的modebus CRC16计算,附上对应的C语言的CRC16