varch/doc/varch:check校验算法.md
2024-04-22 00:09:51 +08:00

109 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 介绍
数据在传输过程中可能会因为各种原因导致产生了差错,为了能够控制传输过程的差错,通信系统往往会采用数据校验来保证数据的完整性。
常见的数据校验算法就包含求和校验、奇偶校验、异或校验、LRC校验、CRC校验这里也给出了常用的校验算法的代码。
## 接口
```c
uint8_t check_sum(uint8_t* data, uint32_t len); // 求和校验算法
uint8_t check_parity(uint8_t* data, uint32_t len); // 奇偶校验
uint8_t check_lrc(uint8_t* data, uint32_t len); // LRC校验
uint8_t check_xor(uint8_t* data, uint32_t len); // 异或校验
```
这几种校验算法使用方法一致,都是传入数据地址和数据长度,返回计算出来的校验值。
### 通用crc
```c
// 通用CRC算法
uint32_t check_crc(uint8_t* data, uint32_t len, uint8_t width, uint32_t poly, uint32_t init, uint8_t refin, uint8_t refout, uint32_t xorout);
```
这个CRC算法是32byte以内的通用CRC算法除了传入数据地址和数据长度后面依次跟着CRC校验码宽度、多项式、初始值、输入翻转、输出翻转、异或输出。
这个算法和 [CRC循环冗余校验在线计算](http://www.ip33.com/crc.html) 的使用方法一致。
在`check_crc`随机计算个crc与在线工具对比
```c
printf("crc 0x%X\r\n", check_crc("Hello", 5, 8, 0x5A, 0xAA, 1, 0, 0x4A));
```
结果都是
```
crc 0xE0
```
根据常用的crc算法可以通过`check_crc`宏定义实现
```c
/*
|-------------------------------------------------------------------------------------------|
|CRC name | width | poly | init | xorout | refin | refout |
|-------------------------------------------------------------------------------------------|
|CRC-4/ITU | 4 | 03 | 00 | 00 | true | true |
|CRC-5/EPC | 5 | 9 | 09 | 00 | false | false |
|CRC-5/ITU | 5 | 5 | 00 | 00 | true | true |
|CRC-5/USB | 5 | 5 | 1F | 1F | true | true |
|CRC-6/ITU | 6 | 3 | 00 | 00 | true | true |
|CRC-7/MMC | 7 | 9 | 00 | 00 | false | false |
|CRC-8 | 8 | 7 | 00 | 00 | false | false |
|CRC-8/ITU | 8 | 7 | 00 | 55 | false | false |
|CRC-8/ROHC | 8 | 7 | FF | 00 | true | true |
|CRC-8/MAXIM | 8 | 1 | 00 | 00 | true | true |
|CRC-16/IBM | 16 | 005 | 0000 | 0000 | true | true |
|CRC-16/MAXIM | 16 | 005 | 0000 | FFFF | true | true |
|CRC-16/USB | 16 | 005 | FFFF | FFFF | true | true |
|CRC-16/MODBUS | 16 | 005 | FFFF | 0000 | true | true |
|CRC-16/CCITT | 16 | 021 | 0000 | 0000 | true | true |
|CRC-16/CCITT-FALSE | 16 | 021 | FFFF | 0000 | false | false |
|CRC-16/X25 | 16 | 021 | FFFF | FFFF | true | true |
|CRC-16/XMODEM | 16 | 021 | 0000 | 0000 | false | false |
|CRC-16/DNP | 16 | D65 | 0000 | FFFF | true | true |
|CRC-32 | 32 | 4C11DB7 | FFFFFFFF | FFFFFFFF | true | true |
|CRC-32/MPEG-2 | 32 | 4C11DB7 | FFFFFFFF | 00000000 | false | false |
|-------------------------------------------------------------------------------------------|
*/
#define check_crc4_itu(data, len) check_crc(data, len, 4, 0x03, 0x00, 1, 1, 0x00)
#define check_crc5_epc(data, len) check_crc(data, len, 5, 0x09, 0x09, 0, 0, 0x00)
#define check_crc5_usb(data, len) check_crc(data, len, 5, 0x05, 0x1F, 1, 1, 0x1F)
#define check_crc6_itu(data, len) check_crc(data, len, 6, 0x03, 0x00, 1, 1, 0x00)
#define check_crc7_mmc(data, len) check_crc(data, len, 7, 0x09, 0x00, 0, 0, 0x00)
#define check_crc8(data, len) check_crc(data, len, 8, 0x07, 0x00, 0, 0, 0x00)
#define check_crc8_itu(data, len) check_crc(data, len, 8, 0x07, 0x00, 0, 0, 0x55)
#define check_crc8_rohc(data, len) check_crc(data, len, 8, 0x07, 0xFF, 1, 1, 0x00)
#define check_crc8_maxim(data, len) check_crc(data, len, 8, 0x31, 0x00, 1, 1, 0x00)
#define check_crc16_ibm(data, len) check_crc(data, len, 16, 0x8005, 0x0000, 1, 1, 0x0000)
#define check_crc16_maxim(data, len) check_crc(data, len, 16, 0x8005, 0x0000, 1, 1, 0xFFFF)
#define check_crc16_usb(data, len) check_crc(data, len, 16, 0x8005, 0xFFFF, 1, 1, 0xFFFF)
#define check_crc16_modbus(data, len) check_crc(data, len, 16, 0x8005, 0xFFFF, 1, 1, 0x0000)
#define check_crc16_ccitt(data, len) check_crc(data, len, 16, 0x1021, 0x0000, 1, 1, 0x0000)
#define check_crc16_ccitt_false(data, len) check_crc(data, len, 16, 0x1021, 0xFFFF, 0, 0, 0x0000)
#define check_crc16_x25(data, len) check_crc(data, len, 16, 0x1021, 0xFFFF, 1, 1, 0xFFFF)
#define check_crc16_xmodem(data, len) check_crc(data, len, 16, 0x1021, 0x0000, 0, 0, 0x0000)
#define check_crc16_dnp(data, len) check_crc(data, len, 16, 0x3D65, 0x0000, 1, 1, 0xFFFF)
#define check_crc32(data, len) check_crc(data, len, 32, 0x04C11DB7, 0xFFFFFFFF, 1, 1, 0xFFFFFFFF)
#define check_crc32_mpeg_2(data, len) check_crc(data, len, 32, 0x04C11DB7, 0xFFFFFFFF, 0, 0, 0x00000000)
```
### 标准crc
如上述通用的crc也能实现标准的crc但是运算起来效率必然有所下降下面是根据标准crc进行的专有的实现
```c
uint8_t crc4_itu(uint8_t* data, uint32_t len);
uint8_t crc5_epc(uint8_t* data, uint32_t len);
uint8_t crc5_itu(uint8_t* data, uint32_t len);
uint8_t crc5_usb(uint8_t* data, uint32_t len);
uint8_t crc6_itu(uint8_t* data, uint32_t len);
uint8_t crc7_mmc(uint8_t* data, uint32_t len);
uint8_t crc8(uint8_t* data, uint32_t len);
uint8_t crc8_itu(uint8_t* data, uint32_t len);
uint8_t crc8_rohc(uint8_t* data, uint32_t len);
uint8_t crc8_maxim(uint8_t* data, uint32_t len);
uint16_t crc16_ibm(uint8_t* data, uint32_t len);
uint16_t crc16_maxim(uint8_t* data, uint32_t len);
uint16_t crc16_usb(uint8_t* data, uint32_t len);
uint16_t crc16_modbus(uint8_t* data, uint32_t len);
uint16_t crc16_ccitt(uint8_t* data, uint32_t len);
uint16_t crc16_ccitt_false(uint8_t* data, uint32_t len);
uint16_t crc16_x25(uint8_t* data, uint32_t len);
uint16_t crc16_xmodem(uint8_t* data, uint32_t len);
uint16_t crc16_dnp(uint8_t* data, uint32_t len);
uint32_t crc32(uint8_t* data, uint32_t len);
uint32_t crc32_mpeg_2(uint8_t* data, uint32_t len);
```