CRC16 MODBUS校验算法,分两种情况,一是参数是字符串,二是参数是字节数组。
参考文章1
参考文章2
直接上代码,第一种参数是字符串
public static void main(String[] args) throws IOException {
String frame = "01 03 01 48 00 0c";
System.out.println(getCRC(frame));
}
public static String getCRC(String data) {
data = data.replace(" ", "");
int len = data.length();
if (!(len % 2 == 0)) {
return "0000";
}
int num = len / 2;
byte[] para = new byte[num];
for (int i = 0; i < num; i++) {
int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
para[i] = (byte) value;
}
return getCRC(para);
}
/**
* 计算CRC16校验码
*
* @param bytes
* 字节数组
* @return {@link String} 校验码
* @since 1.0
*/
public static String getCRC(byte[] bytes) {
// CRC寄存器全为1
int CRC = 0x0000ffff;
// 多项式校验值
int POLYNOMIAL = 0x0000a001;
int i, j;
for (i = 0; i < bytes.length; i++) {
CRC ^= ((int) bytes[i] & 0x000000ff);
for (j = 0; j < 8; j++) {
if ((CRC & 0x00000001) != 0) {
CRC >>= 1;
CRC ^= POLYNOMIAL;
} else {
CRC >>= 1;
}
}
}
// 结果转换为16进制
String result = Integer.toHexString(CRC).toUpperCase();
if (result.length() != 4) {
StringBuffer sb = new StringBuffer("0000");
result = sb.replace(4 - result.length(), 4, result).toString();
}
//高位在前地位在后
//return result.substring(2, 4) + " " + result.substring(0, 2);
// 交换高低位,低位在前高位在后
return result.substring(2, 4) + " " + result.substring(0, 2);
}
执行后结果:
第二种参数是byte数组:
public static void main(String[] args) throws IOException {
byte[] bytes = new byte[] { 0x01, 0x03, 0x01, 0x48, 0x00, 0x0c };
System.out.println(getCRC2(bytes));
}
public static String getCRC2(byte[] bytes) {
int CRC = 0x0000ffff;
int POLYNOMIAL = 0x0000a001;
int i, j;
for (i = 0; i < bytes.length; i++) {
CRC ^= (int) bytes[i];
for (j = 0; j < 8; j++) {
if ((CRC & 0x00000001) == 1) {
CRC >>= 1;
CRC ^= POLYNOMIAL;
} else {
CRC >>= 1;
}
}
}
// 交换高低位,低位在前高位在后
CRC = ((CRC & 0x0000FF00) >> 8) | ((CRC & 0x000000FF) << 8);
String result = Integer.toHexString(CRC);
return result.substring(0, 2) + " " + result.substring(2, 4);
}
运行结果:
小菜一枚,不正确之处还请各位指教!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。