Java实现CRC编码

一、CRC编码简介

CRC 的英文全称为 Cyclic Redundancy Check(Code),中文名称为循环冗余校验(码)。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。

二、CRC编码过程

以下步骤将描述 6 字节红外控制码生成过程:

1.从二维码的中依次顺序提取前 2 个英文字母、最后 2 个英文字母(X、x 除外,取英文字母 ASCII 值为原始数据),并从中提取出多项式 g(x)(多项式的最高位为 x16,最低为 1);

2.预置 1 个 16 位的寄存器为十六进制 FFFF(即全为 1),称此寄存器为 CRC 寄存器;

3.把第一个 8 位二进制数据(既原始数据的第一个字节)与 16 位的 CRC 寄存器的低8 位相异或,把结果放于 CRC 寄存器,高八位数据不变;

4.CRC 寄存器向右移一位,MSB(最高位)补零,并检查右移后的移出位 LSB(最低位)。

5.如果 LSB 为 0,重复第 4 步;若 LSB 为 1,CRC 寄存器与多项式码相异或。

6.重复第 4 与第 5 步直到 8 次移位全部完成。此时一个 8-bit 数据处理完毕。

7.重复第 3 至第 5 步直到将剩下 3 个原始数据全部处理完成。

8.最终 CRC 寄存器的内容即为 CRC 值。

9.取 CRC 的得高八位作为红外控制码的第一字节,按顺序取原始数据为红外控制码的二、三、四、五字节,取 CRC 值的低八位为红外控制码的第六字节。

扫描二维码关注公众号,回复: 8612013 查看本文章

三、算法示例

从二维码中提取的字符串数据为:<Aa12x16,Fg.5tx15/x2+\1/hgBb>,则提取出的 4 个英文字符为 AaBb,多项式 g(x)=x16+x15+x2+1;

提取原始数据为 0x41、 0x61、 0x42 、0x62,多项式码为 0xA001(由多项式忽略了最高位的"1",得到生成项是 0x8005,其中 0xA001 为 0x8005 按位颠倒之后的结果);计算得到的 CRC 码值为 0x8FF4; 所得 6 字节红外控制码为:0x8f 0x41 0x61 0x42 0x62 0xf4。

四、具体代码如下:

import java.util.ArrayList;
import java.util.List;

public class CRC {
    public static void main(String[] args) {
        String s = "<Aa12x16,Fg.5tx15/x2+\1/hgBb>";
        String order = getOrder(s);
        System.out.println(order);
    }

    public static String getOrder(String s){
//		得到前两位和最后两位英文字母
        String result_s = decode_S(s);
        String fin = result_s.subSequence(0, 2).toString().concat(result_s.subSequence(result_s.length()-2,result_s.length()).toString());
        System.out.println("提取出的4个字母:" + fin);
//		将得到的字母的ASCII码值存储在char数组中
        byte []data = new byte[4];
        for(int i = 0; i < fin.length(); i++) {
            byte temp = (byte) (fin.charAt(i) - 1 + 1);
            data[i] = temp;
        }

//		通过char数组得到CRC
        String CRC = getCRC(data);
        String first ="0x" + CRC.substring(0, 2);//第一位十六进制
        String last = "0x" + CRC.substring(2,4);//最后一位
        System.out.println("CRC = " + CRC);

//		将指令进行拼接
        String order = "";
        for (int i = 0; i < data.length; i++) {
            String tem = "0x" + decimalToHex(data[i]) + ",";
            order += tem;
        }
        order = first + "," + order + last;
        return order;
    }

    public static String decode_S(String data){
        String res = "";
        for (int i = 0; i < data.length(); i++) {
            char temp = data.charAt(i);
            if(((temp >= 'a') && (temp <= 'z')) || ((temp >= 'A') && (temp <= 'Z'))){
                if((temp != 'x') && (temp != 'X')){
                    res += temp;
                }
            }
        }
        return res;
    }

//    public static String decode_N(String data){
//        String res = "";
//        for (int i = (data.indexOf('x') - 1); i < data.length(); i++) {
//            char temp = data.charAt(i);
//            if((temp == 'x') || (temp == 'X')){
//                res += temp;
//                for (int j = i + 1; j < i + 3; j++) {
//                    char next = data.charAt(j);
//                    if((next >= '1') && (next <= '9')){
//                        res += next;
//                    }
//                }
//                res += "+";
//            }
//        }
//        return res;
//    }

    public static String getCRC(byte[] bytes) {
        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 Integer.toHexString(CRC);
    }

    public static String decimalToHex(int decimal) {
        String hex = "";
        while(decimal != 0) {
            int hexValue = decimal % 16;
            hex = toHexChar(hexValue) + hex;
            decimal = decimal / 16;
        }
        return  hex;
    }

    //将0~15的十进制数转换成0~F的十六进制数
    public static char toHexChar(int hexValue) {
        if(hexValue <= 9 && hexValue >= 0)
            return (char)(hexValue + '0');
        else
            return (char)(hexValue - 10 + 'A');
    }
}
//得到多项式  多项式码
//String result_Num = decode_N(s) + "1";
//System.out.println("g(x)=" + result_Num);

五、运行结果

在这里插入图片描述
作者留言:距离除夕夜还有八天,目前自己还在留校,过几天也要回家了。提前祝能看到这的陌生人新年快乐,新的一年一起加油!奥利给!

发布了2 篇原创文章 · 获赞 3 · 访问量 110

猜你喜欢

转载自blog.csdn.net/Dimpies/article/details/103984615
CRC