天天看點

奇偶校驗,異或校驗,和校驗,nios序列槽校驗

1.                     奇偶校驗

奇偶校驗是檢錯中比較常見的一種方法。它利用資料中的1的個數作為檢錯的标志位,若1的個數為奇數個,則錯誤檢測的标志位為1,若1的個數為偶數,則錯誤檢測的标志位為0。在發送端和接收端同時檢測奇偶位,若得到相同的結果,則說明資料傳輸過程無錯誤發生;若得到不同的結果,則說明資料傳輸過程中有錯誤發生,此時下位機可以發送一個錯誤重傳的信号,讓上位機再次發送資料。目前網上很多的序列槽收發工具,不具有奇偶校驗功能,是以大多數使用。

2.異或校驗又稱異或和校驗或者BCC校驗

BCC check是比較常用的序列槽資料校驗。檢驗和的概念一般展現在8bit長度的字元數組 ,

注意 :異或校驗是異或運算,需要先強制把字元轉換成整形資料。

NIOS序列槽程式異或校驗

static void uart_ISR(void)

{    

       alt_u8 data_temp;

       alt_u8 add_temp;

       while( !(UART->STATUS.BITS.RRDY));

       data_temp = UART->RXDATA.BITS.RECEIVE_DATA;

//     uart_send_byte(UART->RXDATA.BITS.RECEIVE_DATA);

       if( data_temp == 0x7e &&my_uart.receive_count == 0 )

          {

                 my_uart.receive_buffer[0] =0x7e;

                 my_uart.receive_count = 1;

          }

          else if( my_uart.receive_count == 1 )

          {

                 if( data_temp == 0xff)

                 {

                        my_uart.receive_buffer[1]= 0xff;

                        my_uart.receive_count= 2;

                 }

                 else

                        my_uart.receive_count= 0;

          }

          else if( my_uart.receive_count > 1 && my_uart.receive_count< 8 )

          {

                 my_uart.receive_buffer[my_uart.receive_count++]= data_temp;

                     if(my_uart.receive_count== 8)

                     {

                            add_temp = my_uart.receive_buffer[1]^my_uart.receive_buffer[2]^my_uart.receive_buffer[3]^my_uart.receive_buffer[4]^my_uart.receive_buffer[5];

       //                   uart_send_string(5,my_uart.receive_buffer );

                            if( my_uart.receive_buffer[6]== add_temp && my_uart.receive_buffer[7] == 0xe7 )

                            {

                                   my_uart.receive_flag= 1;

                            }

                            my_uart.receive_count= 0;

                     }

          }

    UART->STATUS.WORD=0;

}

3.和校驗又稱累加和校驗

a.RFC1071源碼

 unsigned short csum(unsigned char *addr, int count){ 

 register long sum = 0; 

 while( count &gt; 1 ){ 

sum += * (unsigned short) addr++; 

count -= 2; 

 } 

 if( count &gt; 0 ) 

 sum += * (unsigned char *) addr; 

 while (sum&gt;&gt;16) 

 sum = (sum &amp; 0xffff) + (sum &gt;&gt; 16); 

 return ~sum; 

  第一個while循環是做普通加法(2進制補碼加法),因為IP標頭和TCP整個封包段比較短(沒達到2^17數量級),是以不可能導緻4位元組的sum溢出(unsigned long 一般至少為4位元組)).  

緊接着的一個判斷語句是為了能處理輸入資料是奇數個位元組的這種情況.再接着的資料循環是實作反碼算法(在前面的普通加法得到的資料的基礎上),由反碼和的高位溢出加到低位的性質,可得到&quot;32位的資料的高位比特移位16

比特,再加上原來的低16比特,不影響最終結果&quot; 這個等價運算,因為sum的最初值(剛開始循環時)可能很大,是以這個等價運算需循環進行,直到sum的高比特(16比特以上)全為0.對于32 位的 sum,

事實上這個運算循環至多隻有兩輪,是以也有程式直接用兩條&quot;sum = (sum &amp; 0xffff) + (sum &gt;&gt; 16);&quot;代

替了整個循環.最後,對和取反傳回.   

b.對資料長度沒限制的實作  

unsigned short cksum (struct ip *ip, int len){  

 long sum = 0; 

 while ( len &gt;1 ){ 

 sum += *((unsigned short *) ip)++; 

 if (sum &amp; 8x00000000) 

 sum = (sum &amp; 0xFFFF) + (sum&gt;&gt; 16)  

 len -= 2; 

 }  

if ( len ) 

 sum += ( unsigned short ) * (unsignedl char *) ip; 

 while ( sum &gt;&gt; 16) 

 sum =(sum &amp; 0xFFFF) + (sum&gt;&gt; 16); 

 return ~sum; 

 這個實作與前面的一個的最大的不同是對資料的長度沒什麼限制了,因為它在第一個循環的加法運算中實時檢測sum的高位的值,一旦發現其有溢出的危險,就及時運用等價運算關系消除了這個危險.