CRC16校验原理及实现
来源:互联网 发布:毕业论文算法 编辑:程序博客网 时间:2024/05/29 16:50
CRC码由发送端计算,放置于发送信息报文的尾部。接收信息的设备再重新计算接收到信息报文的CRC,比较计算得到的CRC是否与接收到的相符,如果两者不相符,则表明出错。 校验码的计算多项式为(X16 + X15 + X2 + 1)。具体CRC16码的计算方法是: 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)进行异或;(Modbus) 5.重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理; 6.重复步骤2到步骤5,进行通讯信息帧下一个字节的处理; 7.将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换; 8.最后得到的CRC寄存器内容即为:CRC码。
具体代码类如下:
public class Crcheck { 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(); } /** * 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); }}
阅读全文
0 0
- CRC16校验原理及实现
- CRC16校验原理总结
- CRC16校验原理总结
- CRC16校验原理总结
- CRC16校验原理总结
- CRC16校验算法实现
- CRC16校验算法实现
- CRC16校验算法实现
- CRC16校验算法实现
- crc16 校验代码C语言实现 和原理分析
- CRC原理详解(附crc16校验代码)
- CRC32校验原理及实现
- CRC32校验原理及实现
- CRC16 校验
- CRC16校验
- CRC16校验
- CRC16校验
- CRC16校验
- Redis支持的两种持久化备份方式(RDB & AOF)
- android获取屏幕的分辨率方法
- <安彦>Java中JVM的原理一
- svn使用教程
- CSS样式学习
- CRC16校验原理及实现
- 25张图让你读懂神经网络架构
- Spark:通过start-slaves.sh脚本启动worker报错:Permission denied
- quartz配置使用及扩展(支持集群)
- man hdparm
- 微服务设计读书笔记
- php 微信支付sdk报错解决办法
- PAT 1003我要通过!
- Xcode8出现AQDefaultDevice (173): skipping input stream 0 0 0x0