Java CRC16校驗(yàn)算法實(shí)現(xiàn)

前言

CSDN博客地址
GitHub https://github.com/MrQ-Android

最近在操作藍(lán)牙的時(shí)候脸爱,遇到一個(gè)需求,按照協(xié)議需要有一個(gè)CRC16的校驗(yàn),方便協(xié)議傳輸?shù)臅r(shí)候校驗(yàn)接受的值是不是正確

算法描述
CRC16 校驗(yàn)算法:
校驗(yàn)(CRC)占用兩個(gè)字節(jié),包含了一個(gè) 16 位的二進(jìn)制值臭蚁。CRC 值由傳輸設(shè)備
計(jì)算出來,然后附加到數(shù)據(jù)幀上,接收設(shè)備在接收數(shù)據(jù)時(shí)重新計(jì)算 CRC 值,然后與
接收到的 CRC 域中的值進(jìn)行比較,如果這兩個(gè)值不相等,就表示數(shù)據(jù)傳輸發(fā)生了錯(cuò)
誤。生成一個(gè) CRC 的流程為:
第一步:預(yù)置一個(gè) 16 位寄存器為 0FFFFH(全 1)
,稱之為 CRC 寄存器讯赏。
第二步:把數(shù)據(jù)幀中的第一個(gè)字節(jié)的 8 位與 CRC 寄存器中的低位字節(jié)進(jìn)行異或
運(yùn)算,結(jié)果存回 CRC 寄存器垮兑。
第三步:將 CRC 寄存器向右移一位,最高位填以 0,最低位移出并檢測(cè)。
第四步:如果最低位為 0:重復(fù)第三步(下一次移位);如果最低位為 1:將 CRC
寄存器與生成多項(xiàng)式(CRC16 多項(xiàng)式對(duì)應(yīng)值 A001H)進(jìn)行異或運(yùn)算漱挎。
第五步:重復(fù)第三步和第四步直到 8 次移位系枪。這樣處理完了一個(gè)完整的八位。
第六步:重復(fù)第二步到第五步來處理下一個(gè)八位,直到所有的字節(jié)處理結(jié)束磕谅。
最終 CRC 寄存器的值就是 CRC 的值

以下是工具類 對(duì)外接口是calcCrc16(byte[] data) 最后一個(gè)方法是需求需要 不是包含在crc里面的

public class CRC16Util {
    static byte[] crc16_tab_h = {(byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0,
        (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
        (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
        (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
        (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40};

    static byte[] crc16_tab_l = {(byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12,
        (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7,
        (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74,
        (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98, (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D,
        (byte) 0x4C, (byte) 0x8C, (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40};

/**
 * 計(jì)算CRC16校驗(yàn)  對(duì)外的接口
 *
 * @param data 需要計(jì)算的數(shù)組
 * @return CRC16校驗(yàn)值
 */
public static int calcCrc16(byte[] data) {
    return calcCrc16(data, 0, data.length);
}

/**
 * 計(jì)算CRC16校驗(yàn)
 *
 * @param data   需要計(jì)算的數(shù)組
 * @param offset 起始位置
 * @param len    長(zhǎng)度
 * @return CRC16校驗(yàn)值
 */
public static int calcCrc16(byte[] data, int offset, int len) {
    return calcCrc16(data, offset, len, 0xffff);
}

/**
 * 計(jì)算CRC16校驗(yàn)
 *
 * @param data   需要計(jì)算的數(shù)組
 * @param offset 起始位置
 * @param len    長(zhǎng)度
 * @param preval 之前的校驗(yàn)值
 * @return CRC16校驗(yàn)值
 */
public static int calcCrc16(byte[] data, int offset, int len, int preval) {
    int ucCRCHi = (preval & 0xff00) >> 8;
    int ucCRCLo = preval & 0x00ff;
    int iIndex;
    for (int i = 0; i < len; ++i) {
        iIndex = (ucCRCLo ^ data[offset + i]) & 0x00ff;
        ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex];
        ucCRCHi = crc16_tab_l[iIndex];
    }
    return ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;
}

/**
 * 將計(jì)算的CRC值 轉(zhuǎn)換為加空格的  比如  : crc值為 A30A -> A3 0A
 * @param res
 * @return
 */
  public static String getCrc(int res) {
    String format = String.format("%04x", res);
    String substring = format.substring(0, 2);
    String substring1 = format.substring(2, 4);
    Log.i("BLUEDATA", "crc ---- : " + substring + "  " + substring1);
    return substring.concat(" ").concat(substring1).concat(" ");
}
}

希望這篇文章可以幫助到需要的人,如果還有其他問題或者補(bǔ)充可以評(píng)論~~~
如果有幫助記得點(diǎn)贊哦私爷!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市膊夹,隨后出現(xiàn)的幾起案子衬浑,更是在濱河造成了極大的恐慌,老刑警劉巖放刨,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件工秩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拓诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門侵佃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奠支,你說我怎么就攤上這事馋辈。” “怎么了倍谜?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵迈螟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我尔崔,道長(zhǎng)答毫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任季春,我火速辦了婚禮洗搂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘载弄。我一直安慰自己耘拇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布宇攻。 她就那樣靜靜地躺著惫叛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逞刷。 梳的紋絲不亂的頭發(fā)上嘉涌,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音夸浅,去河邊找鬼仑最。 笑死,一個(gè)胖子當(dāng)著我的面吹牛题篷,可吹牛的內(nèi)容都是我干的词身。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼番枚,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼法严!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起葫笼,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤深啤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后路星,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溯街,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诱桂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呈昔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挥等。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖堤尾,靈堂內(nèi)的尸體忽然破棺而出肝劲,到底是詐尸還是另有隱情,我是刑警寧澤郭宝,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布辞槐,位于F島的核電站,受9級(jí)特大地震影響粘室,放射性物質(zhì)發(fā)生泄漏榄檬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一衔统、第九天 我趴在偏房一處隱蔽的房頂上張望鹿榜。 院中可真熱鬧,春花似錦缰冤、人聲如沸犬缨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至刺彩,卻和暖如春迷郑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背创倔。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工嗡害, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畦攘。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓霸妹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親知押。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叹螟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,117評(píng)論 25 707
  • 首先要講一下CRC16是什么 。 CRC是一種常見的校驗(yàn)台盯,而CRC16呢罢绽,主要是因?yàn)樾r?yàn)結(jié)果是16個(gè)位,當(dāng)然還有C...
    一路向東_lxd閱讀 23,661評(píng)論 1 4
  • 姓名:于川皓 學(xué)號(hào):16140210089 轉(zhuǎn)載自:http://blog.csdn.net/xubin34171...
    道無涯_cc76閱讀 8,130評(píng)論 0 11
  • 親愛的静盅,謝謝你這么多年對(duì)我的陪伴良价,讓我覺得自己是一個(gè)幸福的女人,我愛你,愛你十分明垢。
    張?jiān)?/span>閱讀 142評(píng)論 0 0
  • 早上準(zhǔn)時(shí)出門了蚣常,心里一個(gè)念頭不要遲到,可是到了富力中心附近痊银,還是分不清ABC棟的區(qū)別史隆,來回走了2趟,超過時(shí)間了……...
    A琳子93520閱讀 243評(píng)論 0 0