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 值的低八位为红外控制码的第六字节。

三、算法示例

从二维码中提取的字符串数据为:<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数组得到CRCString 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');elsereturn (char)(hexValue - 10 + 'A');}
}
//得到多项式  多项式码
//String result_Num = decode_N(s) + "1";
//System.out.println("g(x)=" + result_Num);

五、运行结果


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

本文链接:https://my.lmcjl.com/post/6181.html

展开阅读全文

4 评论

留下您的评论.