CRC16

news/2024/12/5 5:27:57/

CRC选择

当数据帧长度在8bits-128bits范围内时,推荐CRC-8(CRC-8能够减少额外比特的开销,且有更好的性能表现)
当数据帧长度在128bits-2048bits范围内时,推荐CRC-12,CRC-16,CRC-CCITT(CRC-12额外比特的开销更小,且用于6bit字符流的传输;对于16bits的标准,更推荐美国标准CRC-16,性能略优于CRC-CCITT);
当因数据帧长度更长、信道不稳定等情况而需要更高的性能时,CRC-32、CRC-32C将是更好的选择;

CRC简介

CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。16位的CRC码产生的规则是先将要发送的二进制序列数左移16位后,再除以一个多项式,最后所得到的余数既是CRC码,

求CRC码所采用模2加减运算法则,既是不带进位和借位的按位加减,这种加减运算实际上就是逻辑上的异或运算,加法和减法等价,乘法和除法运算与普通代数式的乘除法运算是一样,符合同样的规律。生成CRC码的多项式如下,其中CRC-16和CRC-CCITT产生16位的CRC码,而CRC-32则产生的是32位的CRC码。本文不讨论32位的CRC算法,有兴趣的朋友可以根据本文的思路自己去推导计算方法。CRC-16:(美国二进制同步系统中采用)CRC-CCITT:(由欧洲CCITT推荐)CRC-32:接收方将接收到的二进制序列数(包括信息码和CRC码)除以多项式,如果余数为0,则说明传输中无错误发生,否则说明传输有误,关于其原理这里不再多述。用软件计算CRC码时,接收方可以将接收到的信息码求CRC码,比较结果和接收到的CRC码是否相同。

CRC16 标准

目前常用CRC16算法主要是依据以下两种标准:

CRC16 算法

按照使用环境不同,主要有以下三种实现:

  1. 按位计算
    程序空间十分苛刻但 CRC 计算速度要求不高的微控制器系统
  2. 按字节计算
    程序空间较大且 CRC 计算速度要求较高的计算机或微控制器系统,
  3. 半字节计算
    程序空间不太大,且 CRC 计算速度又不可以太慢的微控制器系统。

按位计算流程

  1. CRC-16码由两个字节构成,在开始时CRC寄存器(预置一个16位寄存器,称之为CRC寄存器)的每一位都预置为1,即为0xFFFFH,
  2. 然后把CRC寄存器与8-bit的数据进行异或
  3. 之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB,移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果LSB为零,则无需进行异或。
  4. 重复上述的由高至低的移位8次,第一个8-bit数据处理完毕
  5. 用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。
  6. 所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。
uint16_t CRC16(uint8_t * Msg,uint16_t DataLen)
{uint16_t i = 0;uint16_t j = 0;uint16_t crc16 = 0xFFFF;for (i = 0;i < DataLen;i++){crc16 = crc16 ^ Msg[i];for (j = 0;j < 8;j++){if (crc16 & 0x01)crc16 = (crc16 >> 1) ^ 0xA001; //0xA001为0x8005按bit位颠倒后的生成项else crc16 = crc16 >> 1;}}return crc16 ;
}

CRC16的校验码是两个字节,所以使用 uint16_t类型(unsigned short int)
CRC16要校验的数据位是8位
在求解CRC校验码的过程中,会用到模二除,实际我们最后不关心它的商Q(x),只关心关心余数R(x),它也是两个字节的大小
余数R(x)分为高字节RH(x)和低字节RL(x)两个部分:R(x) = RH(x) * X^8 + RL(x) (这个+,可以理解成异或,也可以理解成+号)
任何数和0异或结果还是这个数

直接查表

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

http://www.ppmy.cn/news/496344.html

相关文章

STC15F2K60S2系列单片机

STC15F2K60S2系列主要性能&#xff1a; ●大容量2048字节片内RAM数据存储器 ●高速&#xff1a;1个时钟/机器周期&#xff0c;增强型8051内核(STC Y5)&#xff0c;速度比传统8051快7&#xff5e;12倍 速度也比STC早期的1T系列单片机(如STC12/11/10系列)的速度快20% ●宽电压&a…

FLTK-Rs 2

Trees 树形结构&#xff0c;允许在树中显示项目&#xff0c;使用add方法发添加条目 use fltk::{prelude::*, *}; use fltk::enums::FrameType;fn main() {let a celet mut win window::Window::default().with_size(400, 300);let mut tree tree::Tree::new(5,5,390,290,&…

Rock 5 RK3588 SBC初次摸索

RADXA Rock 5&#xff08;基于RK3588&#xff09;的初次摸索 硬件平台简述系统安装选择几个系统的介绍系统的安装方式 配件方面 硬件平台简述 RK3588是瑞芯微发布的一款8核&#xff08;4核大4核小&#xff09;ARM架构处理器&#xff0c;许多家都有这个芯片的开发板。 这里使用…

连接器 SM05B-PASS-TBT R/A 5POS 2MM SMD

CONN HEADER SMD R/A 5POS 2MM&#xff0c;连接器 SM05B-PASS-TBT。 品牌&#xff1a;JST 2mm间距PA系列由以下连接器组成: -PA连接器(线对板压接型) -PAF连接器(线对板绝缘置换连接(IDC)型) -PAL连接器(线对线压接式) 这些特征使得形状复杂的haress首次成为具有安全锁定机构…

[单片机][KEIL5] 参数的意义和使用 L #L @L K #K $, #, %, @, ~, ^

使用键序列从Vision传递参数给外部用户程序。 键序列是键码和文件码的组合。 键序列可以使用&#xff0c;例如&#xff0c;在对话框工具&#xff0c;SVCS&#xff0c;选项的目标用户&#xff0c;或从命令行。 以下规则适用: 当从命令行使用时&#xff0c;某些关键代码必须重复…

敏源传感 MTS01 IIC CRC校验程序(x8 + x5 + x4 + 1)

敏源传感 MTS01 IIC CRC校验程序&#xff1a; /* *Name: CRC-8 x8x5x41 * Poly: 0x31 * Init: 0xFF * Refin: False * Refout: False …

C51简介及Keil的使用

前言 此文档主要是针对有一定C/C编程基础&#xff0c;并打算用Keil从事C51开发的开发人员。C51涉及的知识比较多&#xff0c;但是入门基本的开发&#xff0c;还是容易的。 C51简介 1. C51概念 C51继承于C语言&#xff0c;主要运行于51内核的单片机平台。单片机&#xff0c;…

C语言进阶教程(再论struct,union,enum)

文章目录 前言一、struct&#xff0c;union&#xff0c;enum类型大小计算二、应用场景分析总结 前言 本篇文章我们再来讨论struct&#xff0c;union&#xff0c;enum这三大结构。这三大结构很容易让人晕头转向&#xff0c;所以现在我们再来分析一下吧。 一、struct&#xff0…