CRC16校验程序
16位CRC校验码计算程序
16位CRC校验码计算程序在计算机领域,CRC(Cyclic Redundancy Check)是一种常用的错误检测码,用于检测数据传输或存储过程中的错误。
CRC校验码通常是一个16位的二进制数,用于验证数据的完整性。
计算16位CRC校验码的方法如下:1.定义一个16位寄存器,并将其初始化为0。
2.将待校验的数据按位分割,并逐个与16位寄存器的最高位进行异或操作。
3.对每个数据位重复上述异或操作。
4.最后将16位寄存器的值作为CRC校验码。
下面是一个简单的Python代码示例,演示了如何计算16位CRC校验码:```pythondef calculate_crc16(data):crc = 0xFFFF # 16位寄存器,初始值为0xFFFFfor byte in data:crc ^= (byte << 8) # 将当前数据字节与寄存器的高八位进行异或操作for _ in range(8):if crc & 0x8000: # 检查寄存器的最高位是否为1crc = (crc << 1) ^ 0x1021 # 若为1,则将寄存器左移一位,并与0x1021进行异或操作else:crc <<= 1 # 若为0,则将寄存器左移一位return crc & 0xFFFF#示例数据data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE]#计算CRC校验码crc16 = calculate_crc16(data)print(f"CRC16校验码:0x{crc16:04X}")```在上述代码中,`data`列表用于存储待校验的数据,`calculate_crc16`函数用于计算16位CRC校验码。
最后,根据计算结果输出CRC16校验码。
值得注意的是,具体的CRC校验码算法可能因应用场景的不同而有所不同。
typeb 卡 crc16校验算法
typeb 卡 crc16校验算法
CRC-16 (16位循环冗余校验) 是一种常用的错误检测算法,用于检测数据传输或存储中的错误。
以下是 CRC-16 (TYPEB) 的一个简单实现。
请注意,这是一个基本的实现,实际应用中可能需要调整多项式、初始值、反转输入/输出等。
```python
def crc16_typeb(data: bytes) -> int:
crc = 0xFFFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 0x0001:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
return crc
```
这个函数接受一个字节序列(bytes)作为输入,并返回一个16位的CRC 值。
注意,这个函数将反转输入数据的位,因此如果输入数据的位没有被反转,那么在计算CRC之前需要先进行反转。
CRC-16 (TYPEB) 使用的多项式是 0xA001,初始值为 0xFFFF。
CRC16校验C语言程序源码(附完整的可执行的C语言代码)
CRC16校验C 语言程序源码 (附完整的可执行的 C 语言代码)//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的 2种//实现方法进行测试。
方法一:查表法(256长度的校验表)速度快,准确,但是对于单片机设备存储占用大,且校验表长度大,输入时容易岀现错误 // .................. --POPULAR POLYNOMIALS ....................// CCITT: x A 16 + x A 12 + x A 5 + x A 0(0x1021) // CRC-16: x A 16 + xA15 + xA2 + xA0(0x8005)#defi neCRC_16_POLYNOMIALS0x8005const BYTE chCRCHTalbe[]=// CRC 高位字节值表{0x00, 0xC1, 0x81, 0x40, 0x01, OxCO, 0x80, 0x41, 0x01, OxCO, 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 };con st BYTE chCRCLTalbe[] = // CRC 低位字节值表 {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, 0x1代 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, OxD1, OxDO, 0x10, OxFO, 0x30, 0x31, OxF1,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};WORD CRC16_1(BYTE* pchMsg, WORD wDataLe n){BYTE chCRCHi = 0xFF; // 高CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD win dex; // CRC 循环中的索引while (wDataLe n--){// 计算CRCwin dex = chCRCLo A *pchMsg++ ;chCRCLo = chCRCHi A chCRCHTalbe[wl ndex]; chCRCHi =chCRCLTalbe[wi ndex];}return ((chCRCHi << 8) | chCRCLo);}方法一:列表法(简单表)con st WORD wCRCTalbeAbs[]={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800,0xB401,0x5000, 0x9C01,0x8801,0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLe n){WORD wCRC = OxFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLe n; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar A wCRC)& 15] A (wCRC>> 4);wCRC = wCRCTalbeAbs[((chChar >> 4) A wCRC) & 15] A (wCRC >> 4);}return wCRC;}方法二:定义法根据CRC16/MODBUS理直接计算,算法简单但对单片机计算压力大。
crc16 校验 查表法
crc16 校验查表法CRC16校验是一种常用的校验方法,通过查表法实现。
在数据通信中,数据的完整性和准确性是非常重要的,而CRC16校验能够帮助我们检测数据是否出现错误或被篡改。
本文将详细介绍CRC16校验的原理和实现方法。
一、CRC校验简介CRC(Cyclic Redundancy Check)校验是一种基于多项式运算的校验方法,常用于数据通信中的差错检测。
它通过对待校验数据进行一系列的位运算,生成一个与数据长度无关的校验码。
接收方在接收到数据后,同样进行CRC运算,将得到的校验码与发送方发送的校验码进行比对,如果一致,则说明数据在传输过程中没有发生错误。
二、CRC16校验原理CRC16校验是CRC校验的一种,它使用16位的多项式进行计算。
CRC16校验的原理是将待校验数据和一个预设的除数(生成多项式)进行一系列的位运算,最后得到一个16位的校验码。
具体过程如下:1. 预设除数:CRC16校验使用的预设除数是一个16位的二进制数,常用的有多个不同的预设除数,如0x8005、0x1021等。
2. 数据填充:在待校验数据的末尾填充16个0,使得待校验数据的位数和预设除数的位数一致。
3. 初始值设置:将初始值设为全1的16位二进制数。
4. 逐位异或运算:从待校验数据的最高位开始,逐位与初始值进行异或运算,如果结果为1,则将初始值右移一位并与预设除数进行异或运算,如果结果为0,则直接右移一位。
5. 重复上述步骤,直到待校验数据的所有位都进行了异或运算。
6. 得到校验码:最后得到的16位二进制数即为CRC16校验码。
三、CRC16查表法实现CRC16校验的查表法实现相对于位运算的实现更加高效。
查表法的基本思想是将预设除数的所有可能取值及其对应结果存储在一个查表数组中,通过查表的方式来进行CRC16校验的计算。
1. 初始化CRC表:首先需要创建一个256个元素的CRC表,每个元素的值为该位二进制数的CRC16校验码。
最详细易懂的CRC-16校验原理(附源程序)
最详细易懂的CRC-16校验原理(附源程序)1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。
2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘和’取值的多项式一一对应。
例如:代码对应的多项式为X6+X4+X2+X+1,而多项式为X5+X3+X2+X+1对应的代码101111 o标准CRC生成多项式如下表:名称生成多项式简记式*标准引用CRC-4 x4+x+1 3 ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8x8+x6+x4+x3+x2+x10x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI,IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP3、CRC-16校验码的使用:现选择最常用的CRC-16校验,说明它的使用方法。
根据Modbus协议,常规485通讯的信息发送形式如下:地址功能码数据信息校验码1byte 1byte nbyte 2byteCRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。
例如:信息字段代码为:1011001,校验字段为:1010。
发送方:发出的传输字段为:1 0 1 1 0 0 1 1 0 10信息字段校验字段接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,贝y 信息正确。
crc-16校验流程
crc-16校验流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by the editor. I hope that after you download them, they can help yousolve practical problems. The document can be customized and modified after downloading, please adjust and use it according to actual needs, thank you!In addition, our shop provides you with various types of practical materials, such as educational essays, diary appreciation, sentence excerpts, ancient poems, classic articles, topic composition, work summary, word parsing, copy excerpts,other materials and so on, want to know different data formats and writing methods, please pay attention!在现代通信和数据传输中,校验和是一项至关重要的技术。
crc16校验 用VB编写的CRC校验程序
用VB编写的CRC校验程序Private Sub Command1_Click()Dim bcrc%, gp&, bdf& bcrc值为整型, gp值为长整型, bdf值为长整型bcrc = 16 用CRC—16位校验gp = V al("&H" & CStr(Text2.Text) & "&") gp为生成多项式缺省为11021(16进制)bdf = Val("&H" & CStr(Text1.Text) & "&") bdf为原值Text3 = Hex(calcrc(bcrc, gp, bdf)) 为生成的CRC值End SubFunction calcrc(bcrc As Integer, gp As Long, bdf As Long) As LongDim c1&, c2&Dim a1%, prec1&Dim leftvalue%, a1shift%If bdf = 0 Thencalcrc = 0Exit FunctionEnd Ifa1 = (Len(Hex(bdf)) - 1) * 4 a1 ={原值(16进制)的字符数目-1}*4c1 = bdf * 2 ^ bcrc 进行异或运行前,把原值(2进制)后面加16个0leftvalue = Val("&H" & Mid(Hex(bdf), 1, 1)) 原值的左边第1位(最高位)数值(16进制)If leftvalue >= 1 Then a1shift = 1 原值的最高位=1 偏差=1If leftvalue >= 2 Then a1shift = 2 原值的最高位=2或3 偏差=2If leftvalue >= 4 Then a1shift = 3 原值的最高位>=4,<=7 偏差=3If leftvalue >= 8 Then a1shift = 4 原值的最高位>=8 偏差=4a1 = a1 + (a1shift - 1) 原值(后面加16个0)与生成多项式的二进制码的个数差c2 = gp * 2 ^ a1 把生成多项式的后面也相应加a1个0Doprec1 = c1c1 = c1 Xor c2 原值与生成多项式进行异或Doa1 = a1 – 1 a1数值减1If c1 > prec1 Then 如果异或的结果大于原值,说明原值的左边第1位(最高位)为0 c1 = prec1 Xor (gp * 2 ^ a1) 把a1的值减少一位后,继续异或ElseExit DoEnd IfLoopc2 = gp * 2 ^ a1Loop Until c1 <= gp 直至异或的结果小于生成多项式calcrc = c1 所得的异或结果即是CRC值End Function。
crc16 for modbus法
CRC16(循环冗余校验)是一种经典的校验算法,常用于通信协议中数据的完整性验证。
Modbus是一种常见的串行通信协议,广泛应用于工业控制系统中。
在Modbus通信中,数据传输的可靠性是非常重要的,而CRC16正是用来确保数据的完整性和准确性。
1. CRC16算法原理CRC16算法是通过对数据进行多项式运算,得出校验码来验证数据的正确性。
其原理是将数据看作二进制多项式,然后对这个多项式进行模2除法运算,最终得出余数作为校验码。
CRC16算法主要包括三个步骤:(1)预处理:首先要对数据进行预处理,通常是在数据后面添加一个特定的附加码,比如0x0000。
(2)多项式除法:将预处理后的数据看作二进制多项式,再通过模2除法运算,得出余数作为校验码。
(3)校验码附加:将校验码附加到原始数据后面,形成最终的帧数据。
2. CRC16 for Modbus在Modbus通信中,CRC16的计算方式是针对整个数据帧(包括位置区域、功能码、数据等)进行的。
Modbus协议规定了数据帧的格式,其中包括了两个字节的校验码。
CRC16 for Modbus算法与普通的CRC16算法在处理数据时略有不同,具体表现在预处理阶段和校验码的附加上。
3. 实现CRC16 for Modbus实现CRC16 for Modbus的方法有很多种,可以通过查表法,计算法等方式来实现。
其中,查表法是一种高效的实现方式,能够大大提高计算效率。
通过建立一个256个元素的查表数组,可以在计算CRC16校验码时直接查询表格中的数据,而不用每次都进行多次的位运算。
这种实现方式能够大大加速CRC16的计算过程,尤其适用于嵌入式设备等资源受限的环境中。
4. CRC16 for Modbus的应用在实际的工业控制系统中,Modbus通信广泛应用于PLC、传感器、执行器等设备之间的数据通信。
而CRC16 for Modbus的校验方式,则能够确保通信数据的准确性和完整性,避免数据传输过程中出现错误,保证系统的稳定性和可靠性。
单片机crc16程序
单片机crc16程序CRC(循环冗余校验)是一种校验方法,用于检测数据传输过程中的错误。
CRC16是一种16位的CRC校验算法,常用于单片机和通信协议中。
下面是一个简单的C语言实现的CRC16计算程序示例:c.#include <stdio.h>。
#include <stdint.h>。
#define POLYNOMIAL 0x1021。
uint16_t crc16(uint8_t data, uint16_t length) {。
uint16_t crc = 0;uint8_t i;uint8_t j;for (j = 0; j < length; ++j) {。
crc ^= (uint16_t)(data[j] << 8);for (i = 0; i < 8; i++) {。
if (crc & 0x8000) {。
crc = (crc << 1) ^ POLYNOMIAL; } else {。
crc <<= 1;}。
}。
}。
return crc;}。
int main() {。
uint8_t test_data[] = {0x01, 0x02, 0x03, 0x04,0x05};uint16_t crc = crc16(test_data, sizeof(test_data));printf("CRC16: 0x%04X\n", crc);return 0;}。
在这个示例中,我们定义了一个CRC16函数,它接受一个指向数据的指针和数据长度作为输入,并返回计算得到的CRC16校验值。
在主函数中,我们传入了一个测试数据并打印出计算得到的CRC16值。
需要注意的是,不同的应用场景可能会使用不同的CRC16多项式,所以在实际使用时需要根据具体的需求来选择合适的多项式。
另外,以上代码只是一个简单的示例,实际应用中可能还需要考虑字节序、初始值等因素。
crc16校验查表法原理
crc16校验查表法原理CRC16校验是一种常用的循环冗余校验算法,用于验证数据在传输过程中是否发生了错误或损坏。
CRC16校验的查表法原理是通过预先计算并存储一个256个元素的查表表格,通过查表的方式来计算校验值,提高计算效率。
CRC16校验的原理是将待校验的数据按照一定的规则进行计算,生成一个校验值。
这个校验值可以用来验证数据的完整性,如果校验值与接收方计算得到的校验值一致,那么可以认为数据传输是正确的。
我们来看一下CRC16校验的计算过程。
假设待校验的数据为D,校验值为CRC。
CRC的初始值设为0xFFFF。
校验过程中,将D的每个字节与CRC的低8位进行异或运算,得到一个新的CRC值。
然后,将CRC右移8位,并与一个预先定义的多项式进行异或运算。
重复这个过程,直到对D的每个字节都进行了异或运算。
最后,得到的CRC值就是校验结果。
为了提高计算效率,CRC16校验算法使用了查表法。
查表法的基本思想是在计算过程中,通过查表的方式快速地得到CRC的更新值。
具体来说,算法预先计算并存储了一个256个元素的查表表格,表格中每个元素都是一个16位的值。
校验过程中,将D的每个字节作为表格的索引,从表格中取得对应的16位值,然后与CRC进行异或运算,得到一个新的CRC值。
重复这个过程,直到对D的每个字节都进行了异或运算。
最后得到的CRC值就是校验结果。
查表法的优势在于,通过预先计算并存储查表表格,可以避免重复计算。
在校验过程中,只需要根据D的每个字节从表格中查找对应的值,然后进行异或运算,从而大大提高了计算效率。
为了更好地理解CRC16校验的查表法原理,下面举一个简单的例子来说明。
假设待校验的数据为0x12345678,校验值为0xFFFF。
首先,根据这个数据计算CRC值。
根据查表法原理,我们可以预先计算并存储一个256个元素的查表表格,表格中的每个元素都是一个16位的值。
下面是一个简化的查表表格:0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,...根据查表法原理,我们将0x12345678的每个字节作为表格的索引,从表格中查找对应的16位值,并与CRC进行异或运算。
CRC16校验程序文件
CRC16校验程序--------------------------------------------------------------------------------作者:转载//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的3种//实现方法进行测试。
方法1选用了一种常见的查表方法,类似的还有512字//节、256字等查找表的,至于查找表的生成,这里也略过。
// ---------------- POPULAR POL YNOMIALS ----------------// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021)// CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005)#define CRC_16_POL YNOMIALS 0x8005// --------------------------------------------------------------// CRC16计算方法1:使用2个256长度的校验表// --------------------------------------------------------------const BYTE chCRCHTalbe[] = // CRC 高位字节值表{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};const BYTE chCRCLTalbe[] = // CRC 低位字节值表{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};WORD CRC16_1(BYTE* pchMsg, WORD wDataLen){BYTE chCRCHi = 0xFF; // 高CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD wIndex; // CRC循环中的索引while (wDataLen--){// 计算CRCwIndex = chCRCLo ^ *pchMsg++ ;chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];chCRCHi = chCRCLTalbe[wIndex] ;}return ((chCRCHi << 8) | chCRCLo) ;}// --------------------------------------------------------------// CRC16计算方法2:使用简单的校验表// --------------------------------------------------------------const WORD wCRCTalbeAbs[] ={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLen){WORD wCRC = 0xFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLen; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4);wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4);}return wCRC;}// -----------------------------------------------------------------// CRC16计算方法3:使用直接结算的方法// -----------------------------------------------------------------WORD CRC16_3(BYTE* pchMsg, WORD wDataLen){BYTE i, chChar;WORD wCRC = 0xFFFF;while (wDataLen--){chChar = *pchMsg++;chChar = ByteInvert(chChar);wCRC ^= (((WORD) chChar) << 8);for (i = 0; i < 8; i++){if (wCRC & 0x8000)wCRC = (wCRC << 1) ^ CRC_16_POL YNOMIALS;elsewCRC <<= 1;}}wCRC = WordInvert(wCRC);return wCRC;}//试验数据:// 采用Metrowerks CodeWarrior在DSP56F80x平台上,对这3种方法//进行了性能测试。
crc16校验算法c语言
crc16校验算法c语言crc16校验算法是一种常用的数据校验方法,它可以检测出数据传输或存储过程中的错误,并提供纠错的依据。
crc16校验算法的原理是将待校验的数据看作一个多项式,用一个固定的生成多项式对其进行除法运算,得到的余数就是crc16校验码。
生成多项式的选择会影响crc16校验算法的性能,不同的应用场景可能需要不同的生成多项式。
本文主要介绍一种常用的生成多项式,即CRC-CCITT,它的二进制表示为0x1021,十六进制表示为0x11021。
本文将介绍三种实现crc16校验算法c语言的方法,分别是按位计算、按半字节计算和按单字节计算。
这三种方法的原理都是基于生成多项式对数据进行除法运算,但是具体的实现方式有所不同,各有优缺点。
下面分别介绍这三种方法,并给出相应的c语言代码。
按位计算按位计算是最直接的实现方式,它是将待校验的数据和生成多项式按位进行异或运算,得到余数。
这种方法的优点是不需要额外的存储空间,缺点是效率较低,需要循环处理每一位数据。
按位计算的c语言代码如下:#include<stdint.h>#define CRC_CCITT 0x1021//生成多项式//函数名称:crc_cal_by_bit;按位计算CRC//函数参数:uint8_t * ptr;指向发送缓冲区的首字节// uint32_t len;要发送的总字节数//函数返回值:uint16_tuint16_t crc_cal_by_bit(uint8_t*ptr, uint32_t len) {uint32_t crc =0xffff; //初始值while (len--!=0) {for (uint8_t i =0x80; i !=0; i >>=1) { //处理每一位数据crc <<=1; //左移一位if ((crc &0x10000) !=0) //如果最高位为1,则异或生成多项式crc ^=0x11021;if ((*ptr & i) !=0) //如果当前数据位为1,则异或生成多项式crc ^= CRC_CCITT;}ptr++; //指向下一个字节}uint16_t retCrc = (uint16_t)(crc &0xffff); //取低16位作为结果return retCrc;}按半字节计算按半字节计算是对按位计算的优化,它是将待校验的数据和生成多项式按半字节(4位)进行异或运算,得到余数。
CRC16校验-C语言代码
CRC16校验-C语⾔代码//CRC16校验在通讯中应⽤⼴泛,这⾥不对其理论进⾏讨论,只对常见的3种//实现⽅法进⾏测试。
⽅法1选⽤了⼀种常见的查表⽅法,类似的还有512字//节、256字等查找表的,⾄于查找表的⽣成,这⾥也略过。
// ---------------- POPULAR POLYNOMIALS ----------------// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021)// CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005)#define CRC_16_POLYNOMIALS 0x8005// --------------------------------------------------------------// CRC16计算⽅法1:使⽤2个256长度的校验表// --------------------------------------------------------------const BYTE chCRCHTalbe[] = // CRC ⾼位字节值表{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};const BYTE chCRCLTalbe[] = // CRC 低位字节值表{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};WORD CRC16_1(BYTE* pchMsg, WORD wDataLen){BYTE chCRCHi = 0xFF; // ⾼CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD wIndex; // CRC循环中的索引while (wDataLen--){// 计算CRCwIndex = chCRCLo ^ *pchMsg++ ;chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];chCRCHi = chCRCLTalbe[wIndex] ;}return ((chCRCHi << 8) | chCRCLo) ;}// --------------------------------------------------------------// CRC16计算⽅法2:使⽤简单的校验表// --------------------------------------------------------------const WORD wCRCTalbeAbs[] ={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLen){WORD wCRC = 0xFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLen; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4); wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4); } return wCRC;}// -----------------------------------------------------------------// CRC16计算⽅法3:使⽤直接结算的⽅法// -----------------------------------------------------------------WORD CRC16_3(BYTE* pchMsg, WORD wDataLen){BYTE i, chChar;WORD wCRC = 0xFFFF;while (wDataLen--){chChar = *pchMsg++;chChar = ByteInvert(chChar);wCRC ^= (((WORD) chChar) << 8);for (i = 0; i < 8; i++){if (wCRC & 0x8000)wCRC = (wCRC << 1) ^ CRC_16_POLYNOMIALS;elsewCRC <<= 1;}}wCRC = WordInvert(wCRC);return wCRC;}//试验数据:// 采⽤Metrowerks CodeWarrior在DSP56F80x平台上,对这3种⽅法//进⾏了性能测试。
16位crc校验计算程序
16位crc校验计算程序16位CRC校验计算程序1. 简介CRC(Cyclic Redundancy Check)循环冗余校验,是一种数据传输错误检测技术。
它通过在发送端和接收端对数据进行多项式编码和解码来实现数据的完整性验证。
2. 原理CRC校验利用生成多项式G(x)对待传输的数据D(x)进行除法运算,得到余数R(x),将其附加到原始数据后面形成带有冗余信息的新序列T(x),然后将T(x)传送给接收方。
接收方同样使用相同的生成多项式G(x)对接收到的序列进行除法运算,如果余数为0,则认为该序列无误;否则就认为该序列存在差错。
3. 实现步骤(1)定义生成多项式G(X)(2)在待传输的数据D(X)末尾添加k个零作为低阶系数,并且使得这个新构造出来的n+k位二进制串可以被G(X)整除。
(3)将构造好了的n+k位二进制串按照字节分组。
(4)每一组都与一个初始值相异或,并且依次处理每一个字节。
(5)最终得到一个16位长数字作为结果。
4. 代码实现unsigned short crc16(unsigned char *data, unsigned int length){const unsigned short generator = 0x1021; // CRC-CCITT 标准生成多项式 x^16 + x^12 + x^5 + 1 (0x1021) unsigned short crc = 0xFFFF; for (unsigned int i = 0; i < length; ++i){crc ^= data[i] << 8;for (int j = 0; j < 8; ++j){if ((crc & 0x8000))crc = (crc << 1) ^ generator;elsecrc <<= 1;}} return crc;}5. 总结CRC校验是一种简单而有效地检测通信中是否发生错误并纠正错误方法。
crc16校验原理和计算方法
CRC16 校验原理和计算方法
本文介绍了 CRC16 校验的原理和计算方法,包括 CRC16 校验的基本概念、生成多项式、校验过程等。
CRC16 是一种常用的数据校验码,用于检测和校验数据传输中的错误。
CRC16 校验的原理是利用生成多项式对数据进行校验,生成一个校验码,将校验码附加在原始数据后面,接收方使用相同的生成多项式对接收到的数据进行校验,若计算出的校验码与发送方计算出的校验码相同,则数据传输无误。
CRC16 校验方法采用多项式除法运算,在数据位和校验位之间进行运算,并利用校验位的值进行校验。
- 1 -。
16位CRC校验原理与算法分析
16位CRC校验原理与算法分析2007-12-14 09:37这里,不讨论CRC的纠错原理以及为什么要选下面提及的生成多项式,只是针对以下的生成多项式,如何获得CRC校验码,作一个比较详细的说明。
标准CRC生成多项式如下表:名称生成多项式简记式* 标准引用CRC-4 x4+x+1 3ITU G.704CRC-8 x8+x5+x4+1 0x31CRC-8 x8+x2+x1+1 0x07CRC-8 x8+x6+x4+x3+x2+x1 0x5ECRC-12 x12+x11+x3+x+1 80FCRC-16 x16+x15+x2+1 8005 IBM SDLCCRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCSCRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCSCRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP生成多项式的最高位固定的1,故在简记式中忽略最高位1了,如0x1021实际是0x11021。
I、基本算法(人工笔算):以CRC16-CCITT为例进行说明,CRC校验码为16位,生成多项式17位。
假如数据流为4字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0];数据流左移16位,相当于扩大256×256倍,再除以生成多项式0x11021,做不借位的除法运算(相当于按位异或),所得的余数就是CRC校验码。
发送时的数据流为6字节:BYTE[3]、BYTE[2]、BYTE[1]、BYTE[0]、CRC[1]、CRC[0];II、计算机算法1(比特型算法):1)将扩大后的数据流(6字节)高16位(BYTE[3]、BYTE[2])放入一个长度为16的寄存器;2)如果寄存器的首位为1,将寄存器左移1位(寄存器的最低位从下一个字节获得),再与生成多项式的简记式异或;否则仅将寄存器左移1位(寄存器的最低位从下一个字节获得);3)重复第2步,直到数据流(6字节)全部移入寄存器;4)寄存器中的值则为CRC校验码CRC[1]、CRC[0]。
modbus rtu crc16 校验码计算方法
modbus rtu crc16 校验码计算方法
Modbus RTU使用CRC16校验码,其计算方法如下:
1. 初始化为0xFFFF(十六进制)。
2. 从数据帧中的第一个字节开始遍历。
3. 对于每个字节,执行以下操作:
a. 将字节与CRC寄存器的当前值进行按位异或(^)。
b. 将结果向左移动一位(|)。
c. 如果最高位是1,则将CRC寄存器的值增加1。
4. 当遍历完所有字节后,将CRC寄存器的值再次右移一位并重新赋值给CRC校验码。
5. 如果CRC校验码与实际接收到的校验码匹配,则校验通过。
值得注意的是,Modbus RTU的CRC校验码并不是固定不变的,它可能因不同的硬件和通信环境而略有不同。
此外,由于Modbus RTU的帧长度限制,在CRC计算过程中可能需要跳过某些字节,这可能会影响校验码的计算结果。
因此,在实际应用中,需要仔细考虑这些因素,以确保Modbus RTU通信的正确性和可靠性。
CRC8、CRC16校验程序
1.CRC8校验程序*函数名称:generateCRC(char *data, char num)*函数功能: CRC8检验程序*输入参数:char *data:检验数据首地址char num:校验数据字节个数*返回参数:校验值*相关说明:********************************************************************/ char generateCRC(char*data,char num){char i, j, a, cy, cy1=0, crcdata, a1, a2=0, crc=0;for(j=0; j<num; j++){a = *(data + j);a1 = a;for(i = 0; i<8; i++){a = a ^ crc;cy = a & 0x01;if(cy1 != 0)crcdata = 0x80;elsecrcdata = 0;a = crc;if(cy != 0){a = a ^ 0x18;crcdata = 0x80;}elsecrcdata = 0;cy1 = a & 0x01;a >>= 1;a = crcdata | a;crc = a;if(i == 0)a = a1;elsea = a2;crcdata = a & 0x01;a >>= 1;if(crcdata != 0)a = a | 0x80;a2 = a;}}return(crc);}2.CRC16校验程序/******************************************************************* *函数名称:check16crc(unsigned char *inBuffer, unsigned int size)*函数功能: CRC16检验程序*输入参数:unsigned char *inBuffer unsigned int size:校验数据字节个数*返回参数:校验值*相关说明:********************************************************************/ unsigned int check16crc(unsigned char*inBuffer,unsigned int size){unsigned int crc;unsigned int i, j;unsigned char CRC16Lo =0xff;unsigned char CRC16Hi =0xff;//CRC registerunsigned char cl =0x01;unsigned char ch =0xA0;//0xA001unsigned char saveHi,saveLo;for(i = 0; i<size; i++){CRC16Lo = CRC16Lo ^(*(inBuffer + i));for(j=0; j<8; j++){saveHi = CRC16Hi;saveLo = CRC16Lo;CRC16Hi = CRC16Hi >>1;CRC16Lo = CRC16Lo >>1;if((saveHi &0x1)==1){CRC16Lo = CRC16Lo |0x80;}if((saveLo &0x1)==1){CRC16Hi = CRC16Hi ^ ch;CRC16Lo = CRC16Lo ^ cl;}}}crc = CRC16Lo + CRC16Hi * 256;return crc;}。
CRC16校验C语言程序源码-(附完整的可执行的C语言代码)
CRC16校验C语言程序源码(附完整的可执行的C语言代码)//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的2种//实现方法进行测试。
方法一:查表法(256长度的校验表)速度快,准确,但是对于单片机设备存储占用大,且校验表长度大,输入时容易出现错误。
// ---------------- POPULAR POLYNOMIALS ----------------// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021) // CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005) #define CRC_16_POLYNOMIALS 0x8005const BYTE chCRCHTalbe[] = // CRC 高位字节值表{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};const BYTE chCRCLTalbe[] = // CRC 低位字节值表{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};WORD CRC16_1(BYTE* pchMsg, WORD wDataLen){BYTE chCRCHi = 0xFF; // 高CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD wIndex; // CRC循环中的索引while (wDataLen--){// 计算CRCwIndex = chCRCLo ^ *pchMsg++ ;chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];chCRCHi = chCRCLTalbe[wIndex] ;}return ((chCRCHi << 8) | chCRCLo) ;}方法一:列表法(简单表)const WORD wCRCTalbeAbs[] ={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLen){WORD wCRC = 0xFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLen; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4);wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4);}return wCRC;}方法二:定义法根据CRC16/MODBUS原理直接计算,算法简单但对单片机计算压力大。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CRC16校验程序--------------------------------------------------------------------------------作者:转载//CRC16校验在通讯中应用广泛,这里不对其理论进行讨论,只对常见的3种//实现方法进行测试。
方法1选用了一种常见的查表方法,类似的还有512字//节、256字等查找表的,至于查找表的生成,这里也略过。
// ---------------- POPULAR POL YNOMIALS ----------------// CCITT: x^16 + x^12 + x^5 + x^0 (0x1021)// CRC-16: x^16 + x^15 + x^2 + x^0 (0x8005)#define CRC_16_POL YNOMIALS 0x8005// --------------------------------------------------------------// CRC16计算方法1:使用2个256长度的校验表// --------------------------------------------------------------const BYTE chCRCHTalbe[] = // CRC 高位字节值表{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};const BYTE chCRCLTalbe[] = // CRC 低位字节值表{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};WORD CRC16_1(BYTE* pchMsg, WORD wDataLen){BYTE chCRCHi = 0xFF; // 高CRC字节初始化BYTE chCRCLo = 0xFF; // 低CRC字节初始化WORD wIndex; // CRC循环中的索引while (wDataLen--){// 计算CRCwIndex = chCRCLo ^ *pchMsg++ ;chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];chCRCHi = chCRCLTalbe[wIndex] ;}return ((chCRCHi << 8) | chCRCLo) ;}// --------------------------------------------------------------// CRC16计算方法2:使用简单的校验表// --------------------------------------------------------------const WORD wCRCTalbeAbs[] ={0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,};WORD CRC16_2(BYTE* pchMsg, WORD wDataLen){WORD wCRC = 0xFFFF;WORD i;BYTE chChar;for (i = 0; i < wDataLen; i++){chChar = *pchMsg++;wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4);wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4);}return wCRC;}// -----------------------------------------------------------------// CRC16计算方法3:使用直接结算的方法// -----------------------------------------------------------------WORD CRC16_3(BYTE* pchMsg, WORD wDataLen){BYTE i, chChar;WORD wCRC = 0xFFFF;while (wDataLen--){chChar = *pchMsg++;chChar = ByteInvert(chChar);wCRC ^= (((WORD) chChar) << 8);for (i = 0; i < 8; i++){if (wCRC & 0x8000)wCRC = (wCRC << 1) ^ CRC_16_POL YNOMIALS;elsewCRC <<= 1;}}wCRC = WordInvert(wCRC);return wCRC;}//试验数据:// 采用Metrowerks CodeWarrior在DSP56F80x平台上,对这3种方法//进行了性能测试。