<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      痞子衡嵌入式:常用的數據差錯控制技術(3)- 和校驗(Checksum)


        大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是嵌入式里數據差錯控制技術-和校驗

        在系列前一篇文章里,痞子衡給大家介紹了比較簡單的校驗法-奇偶校驗,該校驗法主要是針對byte傳輸校驗而言,而在實際應用中我們不僅要保證byte的完整性,還需要校驗由多個byte組成的數據包packet的完整性。今天痞子衡繼續給大家介紹針對packet校驗的最簡單的校驗法-即和校驗法。

      一、和校驗法基本原理

      1.1 校驗依據

        和校驗法的校驗依據就是判斷一次傳輸的n bytes組成的packet的所有byte累加和結果(僅截取低byte)在傳輸前后是否一致。

      1.2 和校驗位

        為了實現和校驗,通常會在傳輸的這組n bytes數據最后插入一個額外的和校驗字節(byte),用它來記錄這組數據累加和的低byte結果。

      1.3 校驗方法

        前面講到和校驗位實際上是n bytes數據包的累加和,那么一包數據的長度n到底怎么確定呢?為了確定n,我們通常會在一包數據開始的時候額外插入一個信息位標明當前數據包長度。
        在實際應用中,數據包是一包一包連續發送的,如果傳輸過程中發生數據丟失,則會引起數據包的錯位導致接下來一連串數據包的解析錯誤,如何及時發現數據包錯位呢?我們通常還會在數據包最開始的時候再額外插入一個信息位標明一包數據的開始,這個信息位也叫作起始標志字節。
        所以最終完整的數據包變成如下格式:

      起始標志字節(1 byte) 長度字節(1-2 byte) 原始數據位(n bytes) 和校驗字節(1 byte)

        有了上述前導信息位,我們便可以準確找到一包數據中的原始數據位進行累加計算得出和,然后與數據包中的校驗和字節進行比較驗證當前包數據的正確性。
        需要注意的是,對于校驗和字節,有時候并不一定是數據位所有字節之和結果的原碼,也有可能是反碼或補碼(關于三者區別,請參考痞子衡另一篇文章《整數在計算機中的表示》),需要結合不同校驗和應用標準區別對待,否則會導致驗證結果有誤。

      1.4 C代碼實現

        實際中校驗和字節為數據之和byte結果(認定被截斷的bit9為1)的補碼應用較多,因為在驗證數據包時,直接將所有數據連同校驗和字節直接相加得到byte結果為0,即表示數據包正確。此處示例代碼以補碼校驗和為例:

      安裝包:codeblocks-17.12mingw-setup.exe
      集成環境:CodeBlocks 17.12 rev 11256
      編譯器:GNU GCC 5.1.0
      調試器:GNU gdb (GDB) 7.9.1

      // checksum.c
      //////////////////////////////////////////////////////////
      #include <stdint.h>
      
      enum _packet_constants
      {
          kPacketStartByte = 0x5a
      };
      
      #pragma pack(1)
      typedef struct _packet_header
      {
          uint8_t startByte;
          uint8_t length;
      } packet_header_t;
      #pragma pack()
      
      /*!
       * @brief 計算數據塊的checksum(補碼)
       *
       * @param src, 待處理的數據塊.
       * @param lenInBytes, 待處理的數據塊長度.
       */
      uint8_t get_checksum(uint8_t *src,
                           uint32_t lenInBytes)
      {
          uint8_t checksum = 0;
          // 計算數據和,丟棄高bytes
          while (lenInBytes--)
          {
              checksum += *src++;
          }
          // 轉換為補碼
          checksum = (~checksum) + 1;
          return checksum;
      }
      
      /*!
       * @brief 驗證數據包的checksum
       *
       * @param src, 待處理的數據包.
       * @retval 0, 數據包checksum校驗正確.
       * @retval 1, 數據包起始標志字節錯誤.
       * @retval 2, 數據包checksum校驗錯誤.
       */
      int32_t verify_packet(uint8_t *src)
      {
          uint8_t sum = 0;
          packet_header_t *header = (packet_header_t *)src;
          // 校驗數據包頭
          if (header->startByte != kPacketStartByte)
          {
              return 1;
          }
          // 求所有數據及校驗字節之和
          for (uint32_t i = 0; i < header->length; i++)
          {
              sum += *(src + sizeof(packet_header_t) + i);
          }
          // 結果為非0,則checksum錯誤
          if (sum)
          {
              return 2;
          }
      
          return 0;
      }
      
      // main.c
      //////////////////////////////////////////////////////////
      #include <stdio.h>
      #include <stdlib.h>
      #include "checksum.h"
      
      int main(void)
      {
          uint8_t packet[16];
          packet_header_t *header = (packet_header_t *)packet;
          // 填充包頭
          header->startByte = kPacketStartByte;
          header->length = sizeof(packet) - sizeof(packet_header_t);
          // 填充數據
          for (uint32_t i = sizeof(packet_header_t); i < header->length - 1; i++)
          {
              packet[i] = rand();
          }
          // 填充checksum
          packet[sizeof(packet) - 1] = get_checksum(&packet[sizeof(packet_header_t)], header->length - 1);
          // 顯示packet
          for (uint32_t i = 0; i < sizeof(packet); i++)
          {
              printf("packet[%d] = 0x%x\n", i, packet[i]);
          }
      
          // 校驗checksum
          int32_t res = verify_packet(packet);
          printf("check res = %d\n", res);
      
          return 0;
      }
      

      1.5 行業應用

        和校驗由于實現簡單,檢錯性能也算理想,因此應用十分廣泛,就嵌入式而言,比較典型的應用是在各種image格式中。做過編程器或者下載器的朋友肯定會比較了解,常用的image格式有hex、s19,這些image文件都是由多個數據包組成的,在下載image文件時需要對每一包進行和校驗。關于image文件詳情,可參考痞子衡的文章《ARM開發中image文件詳解》。

      二、和校驗法失效分析

        在數據包傳輸中,如果只是單byte發生bit錯誤(無論多少個bit錯誤),和校驗法一定能夠識別出錯誤。即使有多個byte發生bit出錯,大部分情況下和校驗法也能正常檢出。但和校驗法有如下3個明顯的缺陷:

      • 當多個byte發生的bit錯誤發生抵消現象(引起的增量和結果是0x100的倍數),無法識別錯誤。
      • 當packet中byte數據順序發生調換時,無法識別錯誤。
      • 不能糾錯,在發現錯誤后,只能要求重發。

        和校驗法雖然能夠校驗packet,且有一定的錯誤bit檢測能力,但其是把packet當做無序數據包來處理的,有沒有其他比和校驗法更好且能夠校驗數據次序的檢錯方法呢?痞子衡在下篇會繼續聊。

        至此,嵌入式里數據差錯控制技術之和校驗痞子衡便介紹完畢了,掌聲在哪里~~~

      歡迎訂閱

      文章會同時發布到我的 博客園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

      微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

      posted @ 2017-09-13 21:36  痞子衡  閱讀(1815)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 2020国产欧洲精品网站| 色综合视频一区二区三区| 色噜噜狠狠一区二区三区果冻| 深夜释放自己在线观看| 鄂托克前旗| 亚洲一精品一区二区三区| 国产盗摄xxxx视频xxxx| 精品日韩人妻中文字幕| 人人做人人澡人人人爽| 熟妇人妻任你躁在线视频| 黄色三级亚洲男人的天堂| 国产L精品国产亚洲区在线观看 | 国产中文字幕精品免费| 日本一区二区精品色超碰| 中文国产乱码在线人妻一区二区| 亚洲精品一区二区美女| 少妇伦子伦情品无吗| 日韩乱码人妻无码中文字幕| 欧美精品国产综合久久| 色吊丝免费av一区二区| 中国美女a级毛片| 国产欧美精品一区aⅴ影院| 视频一区视频二区视频三| 午夜福利影院不卡影院| 9久9久热精品视频在线观看| 亚洲精品日韩在线丰满| 精品久久久噜噜噜久久久 | 欧美日韩国产一区二区三区欧| 亚洲人成电影网站色mp4| 97色成人综合网站| 亚洲中文字幕久久精品码| 国产激情一区二区三区成人 | 精品国产大片中文字幕| 亚洲国产日韩a在线播放| 人妻18毛片A级毛片免费看| 欧美日本激情| 成人无码精品免费视频在线观看| 成人亚洲狠狠一二三四区| 99麻豆久久精品一区二区| 偷拍一区二区三区在线视频| 国产黄大片在线观看画质优化|