CRC校验原理及其使用 | 您所在的位置:网站首页 › 查表法crc16_x25 › CRC校验原理及其使用 |
目录 何为CRC 为什么需要校验 为什么是CRC CRC的缺点 目录 何为CRC 为什么需要校验 为什么是CRC CRC的缺点 如何进行CRC校验 校验标准式是什么玩意? 常见的CRC校验 CRC校验计算过程 CRC校验代码参考 代码解读 生成CRC8校验表的代码 CRC检验网站 如何进行CRC校验 校验标准式是什么玩意? 常见的CRC校验 生成CRC校验的代码 何为CRCCRC,循环冗余校验码,本质就是一个校验码,用于检测通讯数据是否正确。常见的还有奇偶校验,校验和(所有数据相加)、LRC校验、异或校验、MD5校验等。 为什么需要校验数据传输过程中,由于其他干扰的存在,有概率会出现数据传输错误的现象。为了识别接收的数据是否正确,我们需要在数据传输完成后增加一个校验数据,接收端按照校验规则计算出(所接收数据的)校验码,与发送端的校验码进行对比,两个校验码不相等说明数据传输出错,反之,通讯正确。 为什么是CRC数据校验本身没有优略之分,CRC可以很大程度上识别出数据传输。举个不恰当的例子,奇偶校验可能识别出百分之五十的数据传输错误,CRC可能可以识别到百分之九十;检测的成本也比较低(占用的资源相对少),从性价比上来看,CRC是个很好的校验法。 CRC的缺点循环冗余校验法检验不出来的错的情况:收到的位串虽然是错误的,但是恰巧能被生成多项式整除,这个时候检测不出来 如何进行CRC校验在了解了CRC是什么之后,还需要了解怎么做。 CRC校验的逻辑是将需要校验的数据与校验标准式进行异或运算,也就是模2除法。不懂什么叫模2除法根本没关系,只要理解什么叫异或运算就可以了。 校验标准式是什么玩意?本质就是一个用于异或的值。这个东西的存在的意义就是规范接收端与发送端的异或值。理论上,式子越复杂,通讯错误的识别率就越高。下面的表格就是常见的CRC校验标准式,摘自链接 有没有被标准式的复杂给震慑住?不用怕,它们就是纸老虎,看懂后,你会发现它们连纸老虎都不如。 式子中x的次方只是标位数,后面的计算根本就不需要考虑。 比如 对应的异或值就是 0001 0011 也就是0x13; 是第四位,是第一位,1就是第零位 再看一个 ,对应的异或值就是 0010 1001 也就是0x29; 是第五位,是第三位,1就是第零位 看完两个例子,懂得怎么将标准式转换出异或值就行,这个标准式就是为了得到异或值,没有其他的用处了,是不是很简单。 注:要注意的一点就是,需要根据CRC校验位数对异或值进行取低位,舍高位。 比如 ,对应的异或值是1 0011 0001,也就是0x131,但我们用的是CRC8的话,只需要取低八位,也就是0x31就行; 常见的CRC校验常见的CRC校验有CRC8,CRC16,CRC32,其中CRC8与CRC16用于通讯在嵌入式行业比较常用。 目前我就掌握了CRC8的使用,我看到CRC16,CRC32是只取低8位进行计算,原理上可能也差不多吧。 CRC校验计算过程摘自计算过程 计算过程就是进行异或运算,首先先对数据进行补0处理(CRC8补8位),然后与标准式进行异或计算。 具体计算过程了解一下就行,写程序又不用你来手算,了解原理就好。 CRC校验代码参考代码取自 原代码地址 #include "crcLib.h" /****************************************************************************** * Name: CRC-4/ITU x4+x+1 * Poly: 0x03 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ uint8_t crc4_itu(uint8_t *data, uint16_t length) { uint8_t i; uint8_t crc = 0; // Initial value while(length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0x0C;// 0x0C = (reverse 0x03)>>(8-4) else crc = (crc >> 1); } } return crc; } /****************************************************************************** * Name: CRC-5/EPC x5+x3+1 * Poly: 0x09 * Init: 0x09 * Refin: False * Refout: False * Xorout: 0x00 * Note: *****************************************************************************/ uint8_t crc5_epc(uint8_t *data, uint16_t length) { uint8_t i; uint8_t crc = 0x48; // Initial value: 0x48 = 0x09> 1); } } return crc; } /****************************************************************************** * Name: CRC-5/USB x5+x2+1 * Poly: 0x05 * Init: 0x1F * Refin: True * Refout: True * Xorout: 0x1F * Note: *****************************************************************************/ uint8_t crc5_usb(uint8_t *data, uint16_t length) { uint8_t i; uint8_t crc = 0x1F; // Initial value while(length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0x14;// 0x14 = (reverse 0x05)>>(8-5) else crc = (crc >> 1); } } return crc ^ 0x1F; } /****************************************************************************** * Name: CRC-6/ITU x6+x+1 * Poly: 0x03 * Init: 0x00 * Refin: True * Refout: True * Xorout: 0x00 * Note: *****************************************************************************/ uint8_t crc6_itu(uint8_t *data, uint16_t length) { uint8_t i; uint8_t crc = 0; // Initial value while(length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0x30;// 0x30 = (reverse 0x03)>>(8-6) else crc = (crc >> 1); } } return crc; } /****************************************************************************** * Name: CRC-7/MMC x7+x3+1 * Poly: 0x09 * Init: 0x00 * Refin: False * Refout: False * Xorout: 0x00 * Use: MultiMediaCard,SD,ect. *****************************************************************************/ uint8_t crc7_mmc(uint8_t *data, uint16_t length) { uint8_t i; uint8_t crc = 0; // Initial value while(length--) { crc ^= *data++; // crc ^= *data; data++; for ( i = 0; i < 8; i++ ) { if ( crc & 0x80 ) crc = (crc |
CopyRight 2018-2019 实验室设备网 版权所有 |