最近有个项目,需要与硬件设备进行通讯,采用Modbus协议,故在网上搜集并整理了该工具类,供以后记录并分享使用!
直接上代码
public class CRC16Util {
/**
* 16进制字符串转byte数组
*
* @param hexString 输入参数
* @return byte[]
*/
private static byte[] hexStrToBinaryStr(String hexString) {
if (StringUtils.isEmpty(hexString)) {
return null;
}
hexString = hexString.replaceAll(" ", "");
int len = hexString.length();
int index = 0;
byte[] bytes = new byte[len / 2];
while (index < len) {
String sub = hexString.substring(index, index + 2);
bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
index += 2;
}
return bytes;
}
/**
* 字符串转byte数组
*
* @param hexString 输入参数
* @return byte[]
*/
public static byte[] hexToByte(String hexString) {
return hexStrToBinaryStr(hexString);
}
/**
* 计算CRC16/Modbus校验码 低位在前,高位在后
*
* @param hexString 十六进制字符串
* @return
*/
public static String crcLowToHigh(String hexString) {
int CRC = calc(hexString);
CRC = ((CRC & 0x0000FF00) >> 8) | ((CRC & 0x000000FF) << 8);
return Integer.toHexString(CRC).toUpperCase();
}
/**
* 计算CRC16/Modbus校验码 低位在后,高位在前
*
* @param hexString 十六进制字符串
* @return
*/
public static String crcHighToLow(String hexString) {
return Integer.toHexString(calc(hexString)).toUpperCase();
}
/**
* 实际计算方法
*
* @param hexString 待计算的字符串
* @return int
*/
public static int calc(String hexString) {
byte[] bytes = hexStrToBinaryStr(hexString);
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;
}
}
}
return CRC;
}
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("CRC16Utils");
String str = "FFFF1822A1770201";
logger.debug("original string:{}", str);
String crcLowToHigh = crcLowToHigh(str);
String crcHighToLow = crcHighToLow(str);
//低位在前,高位在后
logger.debug("low bit on first,high bit on last:{}", crcLowToHigh);
//高位在前,低位在后
logger.debug("high bit on first,low bit on last:{}", crcHighToLow);
}
}