crc16校驗演算法
① CRC校驗的演算法
在代數編碼理論中,將一個碼組表示為一個多項式,碼組中各碼元當作多項式的系數。例如 1100101 表示為1·x6+1·x5+0·x4+0·x3+1·x2+0·x+1,即 x6+x5+x2+1。
設編碼前的原始信息多項式為P(x),P(x)的最高冪次加1等於k;生成多項式為G(x),G(x)的最高冪次等於r;CRC多項式為R(x);編碼後的帶CRC的信息多項式為T(x)。
發送方編碼方法:將P(x)乘以xr(即對應的二進制碼序列左移r位),再除以G(x),所得余式即為R(x)。用公式表示為T(x)=xrP(x)+R(x)
接收方解碼方法:將T(x)除以G(x),得到一個數,如果這個余數為0,則說明傳輸中無錯誤發生,否則說明傳輸有誤。
舉例來說,設信息編碼為1100,生成多項式為1011,即P(x)=x3+x2,G(x)=x3+x+1,計算CRC的過程為
xrP(x) =x3(x3+x2) = x6+x5 G(x)= x3+x+1 即 R(x)=x。注意到G(x)最高冪次r=3,得出CRC為010。
如果用豎式除法(計算機的模二,計算過程為
1110 ------- 1011 /1100000 (1100左移3位) 1011 ---- 1110 1011 ----- 1010 1011 ----- 0010 0000 ---- 010 因此,T(x)=(x6+x5)+(x)=x6+x5+x, 即 1100000+010=1100010
如果傳輸無誤,
T(x)= (x6+x5+x)/G(x) = , G(x)= 無余式。回頭看一下上面的豎式除法,如果被除數是1100010,顯然在商第三個1時,就能除盡。
上述推算過程,有助於我們理解CRC的概念。但直接編程來實現上面的演算法,不僅繁瑣,效率也不高。實際上在工程中不會直接這樣去計算和驗證CRC。
下表中列出了一些見於標準的CRC資料:
名稱 生成多項式 簡記式* 應用舉例
CRC-4 x4+x+1 3 ITU G.704
CRC-8 x8+x5+x4+1 31 DS18B20
CRC-12 x12+x11+x3+x2+x+1 80F
CRC-16 x16+x15+x2+1 8005 IBM SDLC
CRC-ITU** x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS,ZigBee
CRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI,IEEE 1394,PPP-FCS
CRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP
* 生成多項式的最高冪次項系數是固定的1,故在簡記式中,將最高的1統一去掉了,如04C11DB7實際上是104C11DB7。 ** 前稱CRC-CCITT。ITU的前身是CCITT。
備註:
(1)生成多項式是標准規定的
(2)CRC校驗碼是基於將位串看作是系數為0或1的多項式,一個k位的數據流可以看作是關於x的從k-1階到0階的k-1次多項式的系數序列。採用此編碼,發送方和接收方必須事先商定一個生成多項式G(x),其高位和低位必須是1。要計算m位的幀M(x)的校驗和,基本思想是將校驗和加在幀的末尾,使這個帶校驗和的幀的多項式能被G(x)除盡。當接收方收到加有校驗和的幀時,用G(x)去除它,如果有餘數,則CRC校驗錯誤,只有沒有餘數的校驗才是正確的。
② CRC16校驗碼如何計算
首先G(X)=X3+X+1可以得出G(x)=1011[G(x)中的1就是二進制第0位為1,X就是第一位為1,沒有X^2,所以第二位為0,X^3則第三位為1。所以就是1011]
M(x)=0011M(x)*x3=0011000
M(x)*x3/G(x)的余數是101所以R(X)=101
CRC碼為:M(x)*x3+R(x)=0011000+010=0011010
在計算機網路通信中
運用CRC校驗時相對於其他校驗方法就有一定的優勢。CRC可以高比例的糾正信息傳輸過程中的錯誤,可以在極短的時間內完成數據校驗碼的計算,並迅速完成糾錯過程,通過數據包自動重發的方式使得計算機的通信速度大幅提高,對通信效率和安全提供了保障。由於CRC演算法檢驗的檢錯能力極強,且檢測成本較低,因此在對於編碼器和電路的檢測中使用較為廣泛。
以上內容參考:網路-CRC
③ 幾種CRC16演算法
一. CRC16演算法首先在源文件頭文件加入表值:[c] view plain ////////////////////////////////////////////////////////////////////////// // CRC16碼表 static WORD const wCRC16Table[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040}; 然後在文件中加入下列函數:[c] view plain ////////////////////////////////////////////////////////////////////////// // 函數功能: CRC16效驗 // 輸入參數: pDataIn: 數據地址 // iLenIn: 數據長度 // 輸出參數: pCRCOut: 2位元組校驗值 void CCRCDlg::CRC16(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut) { WORD wResult = 0; WORD wTableNo = 0; for(int i = 0; i < iLenIn; i++) { wTableNo = ((wResult & 0xff) ^ (pDataIn[i] & 0xff)); wResult = ((wResult >> 8) & 0xff) ^ wCRC16Table[wTableNo]; } *pCRCOut = wResult; } 二.CRC16(MODBUS)[c] view plain ////////////////////////////////////////////////////////////////////////// // CRC MODBUS 效驗 // 輸入參數: pDataIn: 數據地址 // iLenIn: 數據長度 // 輸出參數: pCRCOut: 2位元組校驗值 void CCRCDlg::CheckCRCModBus(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut) { WORD wHi = 0; WORD wLo = 0; WORD wCRC; wCRC = 0xFFFF; for (int i = 0; i < iLenIn; i++) { wCRC = CalcCRCModBus(*pDataIn, wCRC); pDataIn++; } wHi = wCRC / 256; wLo = wCRC % 256; wCRC = (wHi > 1; wCRCIn = wCRCIn & 0x7fff; if(wCheck == 1) { wCRCIn = wCRCIn ^ 0xa001; } wCRCIn = wCRCIn & 0xffff; } return wCRCIn; } 三.CRC16(CCITT的0XFFFF)[c] view plain ////////////////////////////////////////////////////////////////////////// // 函數功能: CRC16效驗(CCITT的0XFFFF效驗) // 輸入參數: pDataIn: 數據地址 // iLenIn: 數據長度 // 輸出參數: pCRCOut: 2位元組校驗值 void CCRCDlg::CRCCCITT(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut) { WORD wTemp = 0; WORD wCRC = 0xffff; for(int i = 0; i < iLenIn; i++) { for(int j = 0; j < 8; j++) { wTemp = ((pDataIn[i] > 8); wCRC
④ CRC16檢驗演算法
public class CRC16 {
public static String getData(String data){
byte[] b=data.getBytes();
short crc=0;
for(int n=0;n<b.length;n++){
for (char i = 0x80; i != 0; i >>= 1)
{
if ((crc&0x8000) != 0)
{
crc <<= 1;
crc ^= 0x1021;
}
else
{
crc <<= 1;
}
if ((b[n]&i) != 0)
{
crc ^= 0x1021;
}
}
}
return Integer.toHexString(crc & 0xFFFF);
}
public static void main(String[] args) {
System.out.println(CRC16.getData("1234567890"));
}
}這個肯定可以 我自己測試通過的
⑤ CRC16校驗是怎麼回事
CRC是序列號的校驗碼 用來驗證序列號對不對的。序列號一般是沒標的要自己讀。給你個讀序列號的程序改下埠就能用:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P2^0; //定義DS18B20埠DQ
sbit BEEP=P3^7 ; //蜂鳴器驅動線
bit presence ;
sbit LCD_RS = P2^6;
sbit LCD_RW = P2^5;
sbit LCD_EN = P2^4;
uchar code cdis1[ ] = ;
uchar code cdis2[ ] = ;
uchar code cdis3[ ] = ;
uchar code cdis4[ ] = ;
unsigned char data display[2] = ;
unsigned char data RomCode[8] = ;
unsigned char Temp;
unsigned char crc;
void beep();
#define delayNOP(); ;
/*******************************************************************/
void delay1(int ms)
{
unsigned char y;
while(ms--)
{
for(y = 0; y<250; y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
/******************************************************************/
/* */
/*檢查LCD忙狀態 */
/*lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數據。 */
/* */
/******************************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/*******************************************************************/
/* */
/*寫指令數據到LCD */
/*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 */
/* */
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*寫顯示數據到LCD */
/*RS=H,RW=L,E=高脈沖,D0-D7=數據。 */
/* */
/*******************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/*******************************************************************/
/* */
/* LCD初始化設定 */
/* */
/*******************************************************************/
void lcd_init()
{
delay1(15);
lcd_wcmd(0x01); //清除LCD的顯示內容
lcd_wcmd(0x38); //16*2顯示,5*7點陣,8位數據
delay1(5);
lcd_wcmd(0x38);
delay1(5);
lcd_wcmd(0x38);
delay1(5);
lcd_wcmd(0x0c); //顯示開,關游標
delay1(5);
lcd_wcmd(0x06); //移動游標
delay1(5);
lcd_wcmd(0x01); //清除LCD的顯示內容
delay1(5);
}
/*******************************************************************/
/* */
/* 設定顯示位置 */
/* */
/*******************************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80); //數據指針=80+地址變數
}
/*******************************************************************/
/* */
/*us級延時函數 */
/* */
/*******************************************************************/
void Delay(unsigned int num)
{
while( --num );
}
/*******************************************************************/
/* */
/*初始化ds1820 */
/* */
/*******************************************************************/
Init_DS18B20(void)
{
DQ = 1; //DQ復位
Delay(8); //稍做延時
DQ = 0; //將DQ拉低
Delay(90); //精確延時 大於 480us
DQ = 1; //拉高匯流排
Delay(8);
presence = DQ; //讀取存在信號
Delay(100);
DQ = 1;
return(presence); //返回信號,0=presence,1= no presence
}
/*******************************************************************/
/* */
/* 讀一位(bit) */
/* */
/*******************************************************************/
uchar read_bit(void)
{
unsigned char i;
DQ = 0; //將DQ 拉低開始讀時間隙
DQ = 1; // then return high
for (i=0; i<3; i++); // 延時15μs
return(DQ); // 返回 DQ 線上的電平值
}
/*******************************************************************/
/* */
/* 讀一個位元組 */
/* */
/*******************************************************************/
ReadOneChar(void)
{
unsigned char i = 0;
unsigned char dat = 0;
//for (i = 8; i > 0; i--)
// {
// read_bit();
// DQ = 0; // 給脈沖信號
// dat >>= 1;
// DQ = 1; // 給脈沖信號
for (i=0;i<8;i++)
{ // 讀取位元組,每次讀取一個位元組
if(read_bit()) dat|=0x01<<i; // 然後將其左移
// if(DQ)
// dat |= 0x80;
Delay(4);
}
return (dat);
}
/*******************************************************************/
/* */
/* 寫一位 */
/* */
/*******************************************************************/
void write_bit(char bitval) {
DQ = 0; // 將DQ 拉低開始寫時間隙
if(bitval==1) DQ =1; // 如果寫1,DQ 返回高電平
Delay(5); // 在時間隙內保持電平值,
DQ = 1; // Delay函數每次循環延時16μs,因此delay(5) = 104μs
}
/*******************************************************************/
/* */
/* 寫一個位元組 */
/* */
/*******************************************************************/
WriteOneChar(unsigned char dat)
{
unsigned char i = 0;
unsigned char temp;
// for (i = 8; i > 0; i--)
// {
for (i=0; i<8; i++) // 寫入位元組, 每次寫入一位
{
// DQ = 0;
// DQ = dat&0x01;
// Delay(5);
// DQ = 1;
temp = dat>>i;
temp &= 0x01;
write_bit(temp);
// dat>>=1;
}
Delay(5);
}
/*******************************************************************/
/* */
/* 讀取64位序列碼 */
/* */
/*******************************************************************/
Read_RomCord(void)
{
unsigned char j;
Init_DS18B20();
WriteOneChar(0x33); // 讀序列碼的操作
for (j = 0; j < 8; j++)
{
RomCode[j] = ReadOneChar() ;
}
}
/*******************************************************************/
/* */
/*DS18B20的CRC8校驗程序 */
/* */
/*******************************************************************/
uchar CRC8()
{
uchar i,x; uchar crcbuff;
crc=0;
for(x = 0; x <8; x++)
{
crcbuff=RomCode[x];
for(i = 0; i < 8; i++)
{
if(((crc ^ crcbuff)&0x01)==0)
crc >>= 1;
else {
crc ^= 0x18; //CRC=X8+X5+X4+1
crc >>= 1;
crc |= 0x80;
}
crcbuff >>= 1;
}
}
return crc;
}
/*******************************************************************/
/* */
/* 數據轉換與顯示 */
/* */
/*******************************************************************/
Disp_RomCode()
{
uchar j;
uchar H_num=0x40; //LCD第二行初始位置
for(j=0;j<8;j++)
{
Temp = RomCode[j];
display[0]=((Temp&0xf0)>>4);
if(display[0]>9)
else
lcd_pos(H_num);
lcd_wdat(display[0]); //高位數顯示
H_num++;
display[1]=(Temp&0x0f);
if(display[1]>9)
else
lcd_pos(H_num);
lcd_wdat(display[1]); //低位數顯示
H_num++;
}
}
/*******************************************************************/
/* */
/* 蜂鳴器響一聲 */
/* */
/*******************************************************************/
void beep()
{
unsigned char y;
for (y=0;y<100;y++)
{
Delay(60);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //關閉蜂鳴器
Delay(40000);
}
/*******************************************************************/
/* */
/* DS18B20 OK 顯示菜單 */
/* */
/*******************************************************************/
void Ok_Menu ()
{
uchar m;
lcd_init(); //初始化LCD
lcd_pos(0); //設置顯示位置為第一行的第1個字元
m = 0;
while(cdis1[m] != '\0')
{ //顯示字元
lcd_wdat(cdis1[m]);
m++;
}
lcd_pos(0x40); //設置顯示位置為第二行第1個字元
m = 0;
while(cdis2[m] != '\0')
{
lcd_wdat(cdis2[m]); //顯示字元
m++;
}
}
/*******************************************************************/
/* */
/* DS18B20 ERROR 顯示菜單 */
/* */
/*******************************************************************/
void Error_Menu ()
{
uchar m;
lcd_init(); //初始化LCD
lcd_pos(0); //設置顯示位置為第一行的第1個字元
m = 0;
while(cdis3[m] != '\0')
{ //顯示字元
lcd_wdat(cdis3[m]);
m++;
}
lcd_pos(0x40); //設置顯示位置為第二行第1個字元
m = 0;
while(cdis4[m] != '\0')
{
lcd_wdat(cdis4[m]); //顯示字元
m++;
}
}
/*******************************************************************/
/* */
/* 主函數 */
/* */
/*******************************************************************/
void main()
{
P0 = 0xff;
P2 = 0xff;
while(1)
{
Ok_Menu ();
Read_RomCord(); //讀取64位序列碼
CRC8(); //CRC效驗
if(crc==0) //CRC效驗正確
{
Disp_RomCode(); //顯示64位序列碼
beep();
}
while(!presence)
{
Init_DS18B20();
delay1(1000);
}
Error_Menu ();
do
{
Init_DS18B20();
beep();
}
while(presence);
}
}
/*******************************************************************/
⑥ crc16的演算法
#define
CRC16_POLYNOMIAL
0x1021
//
CRC_16校驗方式的多項式.
typedef
unsigned
char
uchar;
typedef
unsigned
int
uint;
typedef
unsigned
long
ulong;
typedef
enum
tagBoolean
{
FALSE,
TRUE
}
bool;
ulong
g_ulTable[256];
//
CRC_16方式校驗的初始化函數,
計算CRC_16餘數表.
void
_far
CRC16Init(void)
{
uint
nRemainder;
int
n,
m;
ulong
*pulTable
=
g_ulTable;
for(n
=
0;
n
<
256;
n
++)
{
nRemainder
=
(uint)n
<<
8;
for(m
=
8;
m
>
0;
m
--)
{
if(nRemainder
&
0x8000)
{
nRemainder
=
(nRemainder
<<
1)
^
CRC16_POLYNOMIAL;
}
else
{
nRemainder
=
(nRemainder
<<
1);
}
}
*(pulTable
+
n)
=
nRemainder;
}
}
//
以CRC_16方式計算一個數據塊的CRC值.
//
pucData
-
待校驗的數據塊指針.
//
nBytes
-
數據塊大小,
單位是位元組.
//
返回值是無符號的長整型,
其中低16位有效.
ulong
_far
CRC16Calc(uchar
*pucData,
int
nBytes)
{
uint
nRemainder,
nRet;
int
n;
uchar
index;
ulong
*pulTable
=
g_ulTable;
nRemainder
=
0x0000;
for(n
=
0;
n
<
nBytes;
n
++)
{
index
=
(uchar)CRCBitReflect(*(pucData
+
n),
8)
^
(nRemainder
>>
8);
nRemainder
=
(uint)*(pulTable
+
index)
^
(nRemainder
<<
8);
}
nRet
=
(uint)CRCBitReflect(nRemainder,
16)
^
0x0000;
return(nRet);
}
//
反轉數據的比特位,
反轉後MSB為1.
//
反轉前:
1110100011101110
0010100111100000
//
反轉後:
1111001010001110
1110001011100000
ulong
_far
CRCBitReflect(ulong
ulData,
int
nBits)
{
ulong
ulResult
=
0x00000000L;
int
n;
for(n
=
0;
n
<
nBits;
n
++)
{
if(ulData
&
0x00000001L)
{
ulResult
|=
(ulong)(1L
<<
((nBits
-
1)
-
n));
}
ulData
=
(ulData
>>
1);
}
return(ulResult);
}
⑦ 請教一個crc16校驗演算法的問題:程序每句話是什麼意思,做什麼用的,急用!!謝謝~~
以下內容可能對你有用呀。好好看看就明白了。
CRC校驗
採用CRC-16,即2位元組冗餘循環碼CRC,低位元組在前。CRC碼由發端計算,放置於發送消息幀的尾部,接收端再重新計算接收到信息的CRC碼,比較計算得到的CRC碼是否與接收到的相符,若不符則表明出錯。CRC碼的計算包括整個消息內容,計算時只用8位數據位,而起始位、停止位及可能的校驗位均不參與CRC計算。
CRC校驗可以100%檢測出所有奇數個隨機錯誤。CRC-16校驗可以檢測出長度小於等於16的突發錯誤,可以保證在1014 bit碼元中只含有1位未被檢測出的錯誤。CRC-16的具體演算法有多種,以下是一個例子。
1.置16位寄存器為全1,作為CRC寄存器。
2.把一個8位數據與16位CRC寄存器的低位元組相異或,把結果放於CRC寄存器中。
3.把寄存器的內容右移一位(朝低位),用0填補最高位,檢查最低位(移出位)。
4.如果最低位為0,重復③(再移位);如果最低位為1,CRC寄存器與多項式A001H(1010 0000 0000 0001)進行異或。
5.重復③、④,直到右移8次,這樣整個8位數據全部進行了處理。
6.重復②-⑤,進行下一個8位數據的處理。
7.將一幀的所有數據位元組處理完後得到CRC-16寄存器。
8.將CRC-16寄存器的低位元組和高位元組交換,得到的值即為CRC-16碼。
⑧ CRC16校驗碼查表法的原理是什麼
基本原理是:在K位信息碼後再拼接R位的校驗碼,整個編碼長度為N位,因此,這種編碼也叫(N,K)碼。對於一個給定的(N,K)碼,可以證明存在一個最高次冪為N-K=R的多項式G(x)。根據G(x)可以生成K位信息的校驗碼,而G(x)叫做這個CRC碼的生成多項式。 校驗碼的具體生成過程為:假設要發送的信息用多項式C(X)表示,將C(x)左移R位(可表示成C(x)*xR),這樣C(x)的右邊就會空出R位,這就是校驗碼的位置。用 C(x)*xR 除以生成多項式G(x)得到的余數就是校驗碼。
任意一個由二進制位串組成的代碼都可以和一個系數僅為『0』和『1』取值的多項式一一對應。例如:代碼1010111對應的多項式為x6+x4+x2+x+1,而多項式為x5+x3+x2+x+1對應的代碼101111。