1. 目的
电流数据采集器是RS485 Modbus协议,想通过java实现串口数据的采集,因为涉及到串口通信的CRC校验,所以需要通过java来实现对采集的电流值进行校验,确保每次读到的电流值都是正常的。
2. 什么是ModbusCRC16校验
Modbus协议是一种串行通信协议,被广泛用于设备之间的通信。Modbus协议可以支持多种电气接口和传输介质,包括但不限于RS-232、RS-422、RS-485、以太网(TCP/IP)等。
CRC16校验是一种基于多项式的校验方法,其核心思想是将数据视为一个长的二进制数,通过特定的生成多项式来计算一个短的余数,这个余数就是CRC校验码。
3. CRC16校验步骤
- 初始化:预置一个16位的寄存器为十六进制0xFFFF,称此寄存器为CRC寄存器,多项式为0xA001。
- 数据处理
2.1 将第一个8位二进制数据(通信信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器。
2.2 把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位。
2.3 如果移出位为0,继续右移;如果移出位为1,将CRC寄存器与多项式0xA001异或。
2.4 重复上述步骤,直到处理完8次(即一个字节的所有位) - 重复处理:重复步骤2,处理通信信息帧的下一个字节,直到所有字节处理完毕。
- 结果处理:最终寄存器中的值即为CRC16校验值。
4. 代码实现
public static Byte[] CRC_calculate(byte[] data){int POLYNOMIAL = 0xA001; // CRC-16/IBM 生成多项式0xA001int INITIAL_VALUE = 0xFFFF; // 初始值0xFFFFint crc = INITIAL_VALUE;for (byte b : data) { //遍历所有的字节crc ^= (b & 0xFF); for (int i = 8; i != 0; i--) {if ((crc & 0x0001) != 0) {crc >>= 1;crc ^= POLYNOMIAL;} else {crc >>= 1;}}}List<Byte> list = new ArrayList<>();// MODBUS的低位在前list.add((byte) (crc & 0xff)); // 低位list.add((byte) (crc >> 8)); // 高位return list.toArray(new Byte[0]); // 转换为Byte数组}//主函数public class Main {public static void main(String[] args) {byte[] data = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01};//byte[] data = {0x01, 0x03, 0x02, 0x27, 0x10}; Byte[] crc = CRC_calculate(data);System.out.println("CRC-16 Modbus length: " + crc.length);System.out.println("CRC-16 Modbus1: " + String.format("%X", crc[0]));System.out.println("CRC-16 Modbus2: " + String.format("%X", crc[1]));}
}
5. 结果比对
运行的结果:
由结果可以看出,85 C0与实际一致。
运行的结果:
由结果可以看出,A2 78与实际一致。