1. 程式人生 > >痞子衡隨筆:常用的數據傳輸差錯檢測技術(1)- 奇偶校驗(Parity Check)

痞子衡隨筆:常用的數據傳輸差錯檢測技術(1)- 奇偶校驗(Parity Check)

編碼 和數 作用 除了 實現 1.5 怎麽辦 如果 錯誤


  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是嵌入式數據傳輸裏的差錯檢測技術-奇偶校驗

  在嵌入式應用裏,除了最核心的數據處理外,我們還會經常和數據傳輸打交道。數據傳輸需要硬件傳輸接口的支持,串行接口由於占用引腳少的優點目前應用比並行接口廣泛,常用的串行接口種類非常多,比如UART,SPI,I2C,USB等,在使用這些接口傳輸數據時避不可免會遇到一個問題,如果傳輸過程中遇到未知硬件幹擾發生bit錯誤怎麽辦?

  痞子衡今天給大家講的就是數據傳輸過程中用於差錯檢測的最簡單的方法,即奇偶校驗法。

一、奇偶校驗法基本原理

1.1 校驗依據

  奇偶校驗法的校驗依據就是判斷傳輸的一組二進制數據中"1"的個數是奇數還是偶數,所以其實奇偶檢驗法有兩個子類:

  • 奇校驗:如果以二進制數據中1的個數是奇數為依據,則是奇校驗
  • 偶校驗:如果以二進制數據中1的個數是偶數為依據,則是偶校驗

  一般在同步傳輸方式中常采用奇校驗,而在異步傳輸方式中常采用偶校驗。

1.2 奇偶校驗位

  為了實現奇偶校驗,通常會在傳輸的這組二進制數據中插入一個額外的奇偶校驗位(bit),用它來確保發送出去的這組二進制數據中“1”的個數為奇數或偶數。
  劃重點,奇偶校驗位並不是用來標記原始傳輸數據中1的個數是奇數還是偶數,而是用來確保原始數據加上奇偶校驗位後的合成數據中1的個數是奇數或者偶數。

1.3 校驗方法

  常用的奇偶校驗共有三種:水平奇偶校驗,垂直奇偶校驗校驗和水平垂直奇偶校驗。以對32位數據:10100101 10111001 10000100 00011010進行校驗為例講解:

  • 水平奇偶校驗:對每一種數據的編碼添加校驗位,使信息位與校驗位處於同一行。
原始數據 水平奇校驗位 水平偶校驗位
10100101 1 0
10111001 0 1
10000100 1 0
00011010 0 1

  所以加上水平偶校驗位後應傳輸的數據是:101001010 101110011 100001000 000110101

  • 垂直奇偶校驗:將數據分為若幹組,一組一行,再加上一行校驗位,針對每一列采樣奇校驗或偶校驗。
編碼分類 垂直奇校驗 垂直偶校驗
原始數據 10100101 10100101
10111001 10111001
10000100 10000100
00011010 00011010
校驗位 01111101 10000010

  所以加上垂直偶校驗位後應傳輸的數據是:10100101 10111001 10000100 0001101010000010

  • 水平垂直奇偶校驗:也叫Hamming Code,其是在水平和垂直方向上進行雙校驗,其不僅可以檢測2bit錯誤的具體位置,還可糾正1bit錯誤,常用於NAND Flash裏。這部分不屬於本文要討論的內容,痞子衡後續會專門介紹Hamming Code。

1.4 C代碼實現

  實際中水平校驗法應用比較多,此處示例代碼以水平奇校驗為例:

// 獲取當前byte的極性
// 如byte極性(含1的個數)為奇數,返回ture;否則返回false
bool is_byte_odd_parity(uint8_t byte)
{
    bool parity = false;
    // 普通算法-byte逐位異或(需循環8次)
    /*
    for (uint8_t i = 0; i < 8; i++)
    {
        parity ^= byte & 0x01u;
        byte >>= 1;
    }
    */
    // 效率較高算法-計數byte中1的個數(需循環n次,n為byte中1的個數)
    while (byte)
    {
        parity = !parity;
        byte &= byte - 1;
    }
    return parity;
}

// 獲取給定data的奇校驗位
uint32_t get_data_parity(uint8_t *src,
                         uint32_t lenInBytes)
{
    uint32_t result = 0;
    // 水平校驗法
    // isDataOddParity用於判斷所有data bits的行極性是否為奇
    bool isDataOddParity = false;
    while (lenInBytes--)
    {
        isDataOddParity ^= is_byte_odd_parity(*src++)
    }
    // result為所有data bits的奇校驗位
    result = !isDataOddParity;

    return result;
}

1.5 行業應用

  奇偶檢驗比較典型的應用是在串口UART上,玩過UART的朋友肯定了解串口奇偶檢驗位的作用,包括下位機MCU UART驅動的編寫,上位機串口調試助手的設置都需要註意奇偶校驗位。下圖是UART傳輸時序圖,奇偶校驗位是可選位,僅當使能時才會生效。不過作為嵌入式開發者,倒不必關註奇偶校驗的具體實現,因為MCU的UART模塊已經在硬件上支持了奇偶檢驗,我們只需要操作UART對應寄存器的控制位去使能奇偶檢驗功能即可。

技術分享圖片

二、奇偶校驗法失效分析

  在現實數據傳輸中,偶爾1位出錯的機會最多,2位及以上發生錯誤的概率比較低,且由於奇偶校驗實現簡單,具有相對理想的檢錯能力,因此得到廣泛使用。但奇偶校驗法有如下2個明顯的缺陷:

  • 奇數位誤碼能檢出,偶數位誤碼不能檢出
  • 不能糾錯,在發現錯誤後,只能要求重發。

  有沒有其他比奇偶校驗法更好的檢錯方法?痞子衡在下篇會繼續聊。

  至此,嵌入式數據傳輸裏的差錯檢測技術之奇偶校驗痞子衡便介紹完畢了,掌聲在哪裏~~~

痞子衡隨筆:常用的數據傳輸差錯檢測技術(1)- 奇偶校驗(Parity Check)