• <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        當前位置:雨林木風下載站 > 技術開發教程 > 詳細頁面

        在串口通訊程序中處理數據包

        在串口通訊程序中處理數據包

        更新時間:2022-04-26 文章作者:未知 信息來源:網絡 閱讀次數:

        在串口通訊程序中,經常要收到數據包,常有網友問及如何從這些數據包中提取需要的數據,如何處理校驗等,在這篇文章里我舉兩個例子予以說明,程序說明為VC++6.0。關于串口編程建立程序的細節,請參閱我主頁上的其它文章。同時,此文也適于其它通訊程序中艱數據報文的處理。

            首先,應該指出的是,所有這些處理均在串口事件處理函數oncommunication()中進行。每當串口緩沖區中有一個或一個以上字符時觸發串口通訊事件,該事件就驅動(調用)串口事件通訊處理函數oncommunication(),在這里就可以對接收到的數據進行處理,提取需要的數據。

        舉兩個例子,一個是較為簡單的位數據格式的處理,另一個是NMEA無線通訊格式的處理,最后回答一位網友提出的問題,大家也可以探討一下。

        1.問題:

        一個數據包,其串頭為一個字符,字符值為7EH(16進制)'~',其后緊跟一字符‘E’,然后是數據串,串尾也為字符值為7EH的一個字符:
        即 ~Exxxxxx...~ 如何處理這些數據?
        我們仍以串口調試助手源程序及其詳細編程過程之一 中的OnComm()處理為例:
        void CSCommTestDlg::OnComm()
        {
        // TODO: Add your control notification handler code here
        VARIANT variant_inp;
        COleSafeArray safearray_inp;
        LONG len,k;
        BYTE rxdata[2048]; //設置BYTE數組 An 8-bit integerthat is not signed.
        CString strtemp;
        if(m_ctrlComm.GetCommEvent()==2) //事件值為2表示接收緩沖區內有字符
        { ////////以下你可以根據自己的通信協議加入處理代碼
        variant_inp=m_ctrlComm.GetInput(); //讀緩沖區
        safearray_inp=variant_inp; //VARIANT型變量轉換為ColeSafeArray型變量
        len=safearray_inp.GetOneDimSize(); //得到有效數據長度
        for(k=0;k<len;k++)
        safearray_inp.GetElement(&k,rxdata+k);//轉換為BYTE型數組
        for(k=0;k<len;k++) //將數組轉換為Cstring型變量
        {
        BYTE bt=*(char*)(rxdata+k); //字符型
        strtemp.Format("%c",bt); //將字符送入臨時變量strtemp存放
        m_strRXData+=strtemp; //加入接收編輯框對應字符串,在這兒,編輯框不是必須的,可做相應處理
        char ch=(char)bt;
        if(ch=='E')
        {
        //在此處設置一個可以接收數據的全局標志,說明接收到數據前的‘E’標志了,下一步可以讀數據了,同時將m_strRXData清空
                flag=2;
                 m_strRXData.Empty(); //下一次接收的便為有用的數據
        }
        if(ch==0x7e)
        {
              flag=1; //下面可以提取數據了
        }
        if(flag==1) //標志為1,
        {
             ...//提取數據
                flag=0; //提取完后,置標志為0
        }

        }
        }
        //UpdateData(FALSE); //更新編輯框內容
        }

        2 NMEA無線通訊格式的處理

        2.1 NMEA-0183報文格式

        字符串(ASCII字符)格式如下:
        $XXXX,XX,XX,XX,……*hh<CR><LF>
        $:串頭
        XXXX: 串頭
        XX:數據字段,字母或數字
        XX:數據字段,字母或數字
        XX:數據字段,字母或數字
        ,:逗號
        ……
        *:星號,串尾
        hh:$與*之間所有字符代碼的校驗和,(注意:校驗和h為半Byte校驗,*后第1個h表示高4位校驗和,第2個h表示低4位校驗和。得到校驗值后,再轉換成ASCII字符。)
        <CR>:0DH,回車控制符
        <LF>:0AH,換行控制符

        2.2 校驗處理

        由于數據是動態接收,所以數據的處理也是動態進行,盡管有時會收到幾個字符才觸發一個串口事件,但字符的接收是一個一個接收的,因此就可以在程序中先判斷串頭$是否到達,若串頭到達,就可以開始計算校驗,直至串尾*到達,這時*號后面的兩個字符就是校驗碼,收到這兩個校驗字符,就可以與自己計算的校驗值比較,若不正確,就報錯,并繼續處理下面的數據,若正確,則處理接收的字符,提取需要的數據。


        2.3 程序
        CString m_strReceived;
        CString m_strChecksum;
        int flag;
        char ch為每次收到的字符


        m_strReceived += (char)ch;
        switch(ch)
        {
        case '$':
        checksum=0; //開始計算CheckSum
        flag=0;
        break;
        case '*':
        flag=2;
        c2=checksum & 0x0f; c1=((checksum >> 4) & 0x0f);
        if (c1 < 10) c1+= '0'; else c1 += 'A' - 10;
        if (c2 < 10) c2+= '0'; else c2 += 'A' - 10;
        break;
        case CR:
        break;
        case LF:
        m_strReceived[port-1].Empty();
        break;
        default:
        if(flag>0)
        {
        m_strChecksum += ch;
        if(flag==1)
        {
        strCheck=strCheck+c1+c2;
        if(strCheck!=m_strChecksum)
        {
        m_strReceived.Empty();
        }
        else
        {
        strInstruction=m_strReceived[port-1].Left(6);
        if(strInstruction=="$QGOKU") //如果串頭正確
        {
        char *temp=(char*)((LPCTSTR)m_strReceived);//轉換

        int speed=(atoi(temp+7));// 提取int 型數據
        char splevel=*(temp+25); //提取 char 型數據

        }

        }
        m_strChecksum.Empty();
        }
        flag--;
        }
        else
        checksum=checksum^ch;
        break;
        }



        3 網友的問題

        另外,我回答了一位網友的問題,大家也可以探討一下:
        問題如下3:

        我用你的串口程序收來的十六進制數據是這個樣的:
        00 10 10 C0 00 F0 F0 AB AC AD
        我現在要將高四位取出來,也就是
        011C0FFAAA(這點我不會,但我用Left實現了,可得到的是字符,不是我要的數值)
        我只要011C0FF.
        我要把011C0FF進行如下的處理
        011轉化成十進制
        C不變
        0FF也變成十進制
        后顯示,成 17 C 255

        答:右移得到011C0FF后,可將其放在一個字符型變量CString m_strReceive中:
        然后將其轉換:
        char *temp=(char*)((LPCTSTR)m_strReceive;

        char tbuf[6]; //temporary viable
        tbuf[0]=temp[1]; tbuf[1]=temp[2]; tbuf[2]=temp[3]; tbuf[3]=0; //011 最后為0表示結束
        int data1=atoi(tbuf);
        char chdata2==temp[4]; //C
        tbuf[0]=temp[5]; tbuf[1]=temp[6]; tbuf[2]=temp[7]; tbuf[3]=0;
        int data3=atoi(tbuf); //0FF

        以上data1,chdata2,data3即為你要的數據

        溫馨提示:喜歡本站的話,請收藏一下本站!

        本類教程下載

        系統下載排行

        主站蜘蛛池模板: 中文字幕亚洲综合久久| 久久亚洲AV成人无码国产| 精品免费国产一区二区| 国产成人精品曰本亚洲79ren| 亚洲AV福利天堂一区二区三| 亚洲AV无码资源在线观看| 免费看搞黄视频网站| 国产又大又长又粗又硬的免费视频| 免费v片在线观看| 亚洲日本在线观看| 特级毛片在线大全免费播放| 中文字幕免费视频一| 中文字幕中韩乱码亚洲大片| 亚洲色无码专区一区| 24小时免费看片| 亚洲中文久久精品无码| 国产亚洲综合久久| 久久久久免费看黄A片APP| 亚洲四虎永久在线播放| 9420免费高清在线视频| 亚洲国产91在线| 日本免费xxxx色视频| 亚洲午夜免费视频| 91手机看片国产永久免费| 久久亚洲精品中文字幕| 国产日本一线在线观看免费| 亚洲精品无码久久久久久久| 成全在线观看免费观看大全| 国产亚洲色视频在线| 无码AV片在线观看免费| 亚洲成av人片天堂网| 中文字字幕在线高清免费电影| 亚洲 另类 无码 在线| 色婷婷亚洲一区二区三区| 日本免费人成视频播放| 亚洲一本一道一区二区三区| 亚洲国产成人久久综合野外| 一个人看的www免费高清| 久久久青草青青国产亚洲免观| 免费黄网站在线看| 国产精品亚洲精品爽爽|