JAVA CRC16校验算法

JAVA Modbus CRC16 校验码生成算法

参考文档

校验码: C R C 1 6 ( 1 ) \color{#FF0000}{CRC16^{(1)}} CRC16(1) 占用两个字节,包含了一个 16 位的二进制值。CRC 值由传输设备计算出来,
然后附加到数据帧上,接收设备在接收数据时重新计算 CRC 值,然后与接收到的 CRC 域中的值
进行比较,如果这两个值不相等,就发生了错误。
生成一个 CRC16 的流程为:
(1) 预置一个 16 位寄存器为 0 F F F F H ( 2 ) \color{#FF0000}{0FFFFH}^{(2)} 0FFFFH(2)(全 1),称之为 CRC 寄存器。
(2) 把数据帧中的第一个字节的 8 位与 CRC 寄存器中的低字节进行异或运算,结果存回
CRC 寄存器。
(3) 将 CRC 寄存器向右移一位,最高位填以 0,最低位移出并检测。
(4) 如果最低位为 0:重复第三步(下一次移位);如果最低位为 1:将 CRC 寄存器与一个
预设的固定值( 0 A 001 H ( 3 ) \color{#FF0000}{0A001H}^{(3)} 0A001H(3))进行异或运算。
(5) 重复第三步和第四步直到 8 次移位。这样处理完了一个完整的八位。
(6) 重复第 2 步到第 5 步来处理下一个八位,直到所有的字节处理结束。
(7) 最终 CRC 寄存器的值就是 CRC16 的值。

请注意上述文档中说明的
(1) CRC宽度
(2) 初始值
(3) 多项式

请根据具体项目要求修改修改算法

算法代码

/**
 * Create by 郭文梁 2019/6/25 0025 10:32
 * CRC16
 * CRC16工具类
 *
 * @author 郭文梁
 * @data 2019/6/25 0025
 */
public class CRC {
    /**
     * 一个字节包含位的数量 8
     */
    private static final int BITS_OF_BYTE = 8;
    /**
     * 多项式
     */
    private static final int POLYNOMIAL = 0xA001;
    /**
     * 初始值
     */
    private static final int INITIAL_VALUE = 0xFFFF;

    /**
     * CRC16 编码
     *
     * @param bytes 编码内容
     * @return 编码结果
     */
    public static int crc16(int[] bytes) {
        int res = INITIAL_VALUE;
        for (int data : bytes) {
            res = res ^ data;
            for (int i = 0; i < BITS_OF_BYTE; i++) {
                res = (res & 0x0001) == 1 ? (res >> 1) ^ POLYNOMIAL : res >> 1;
            }
        }
        return revert(res);
    }

    /**
     * 翻转16位的高八位和低八位字节
     *
     * @param src 翻转数字
     * @return 翻转结果
     */
    private static int revert(int src) {
        int lowByte = (src & 0xFF00) >> 8;
        int highByte = (src & 0x00FF) << 8;
        return lowByte | highByte;
    }
}

补充说明

由于文档中提到如下内容

数据帧的结构,即报文格式:

设备地址 功能代码 数据段 CRC16校验码
1个byte 1个byte N个byte 2个byte( 低 字 节 在 前 \color{#FF0000}{低字节在前} )

故代码中使用了 revert 函数翻转了16位CRC校验值的高低位

测试代码

参考测试结果
JAVA CRC16校验算法_第1张图片
测试代码

package club.xyes.zkh.retail.commons.utils;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

@Slf4j
public class CRC16Test {
    @Test
    public void test() {
        final int[] data = {
                0x01,
                0x10,
                0x00,
                0x0C,
                0x00,
                0x02,
                0x04,
                0x00,
                0x00,
                0x00,
                0x00
        };
        final int res = CRC.crc16(data);
        final String hex = Integer.toHexString(res);
        log.debug("Res hex {}", hex);
    }
}

输出

13:41:48.397 [main] DEBUG club.xyes.zkh.retail.commons.utils.CRC16Test - Res hex f3fa

你可能感兴趣的:(java,算法)