<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • RS485網(wǎng)絡(luò)的整幀數(shù)據(jù)收發(fā)

     2020-7-28     作者:黃志超         

      背景:RS485是最常用的工業(yè)現(xiàn)場(chǎng)通訊手段,它的傳輸字節(jié)采用了異步串口UART的規(guī)范。在通常的工控應(yīng)用中,需要傳輸由多個(gè)字節(jié)組成的數(shù)據(jù)幀,而RS485并沒有對(duì)數(shù)據(jù)幀有任何規(guī)范,需要應(yīng)用程序自己做數(shù)據(jù)幀的鑒別。


      本文介紹在ESM6800、ESM7000和ESM8000主板上,利用iMX6/7/8串口的9bit RS485模式,實(shí)現(xiàn)RS485通訊網(wǎng)絡(luò)的整幀數(shù)據(jù)收發(fā)的功能。該功能可大大簡(jiǎn)化應(yīng)用程序接收線程的復(fù)雜性,提高RS485通訊的效率。


      整幀數(shù)據(jù)擁有固定的數(shù)據(jù)長(zhǎng)度,由地址和數(shù)據(jù)構(gòu)成,地址為一個(gè)字節(jié),其余都為數(shù)據(jù)字節(jié),如下圖:


    RS485網(wǎng)絡(luò)的整幀數(shù)據(jù)收發(fā).png


      9bit RS485模式使用了串口固定校驗(yàn)位的功能,定義了地址字節(jié)和數(shù)據(jù)字節(jié),地址字節(jié)是指固定校驗(yàn)位始終為1的字節(jié)。而數(shù)據(jù)字節(jié)則是指固定校驗(yàn)位始終為0的字節(jié)。同時(shí)9bit RS485模式實(shí)現(xiàn)了一些硬件過濾的功能,在接收的時(shí)候,必須要先接收到地址字節(jié)才會(huì)開始接收數(shù)據(jù)字節(jié),否則硬件會(huì)將收到的數(shù)據(jù)字節(jié)全部過濾掉,通過這種方式降低了設(shè)備的負(fù)載。所以9bit RS485模式顧名思義,通常使用在RS485模式上面,因?yàn)镽S485可以作為總線掛接多個(gè)設(shè)備,在多路設(shè)備通訊的情況下通過這種校驗(yàn)方式可以有效的降低設(shè)備負(fù)載和軟件的復(fù)雜程度。


      英創(chuàng)工控主板中,能夠支持9bit RS485模式的主板和串口如下表,其中ES6801/ES6801L和ESM6800L這三款核心板能夠滿足低成本的需求,可以考慮作為RS485網(wǎng)絡(luò)中的Slave端:


    主板型號(hào)支持9bit RS485模式的串口備注
    ES6801(L)ttyS1—ttyS6適合作為Slave
    ESM6800(H)ttyS1—ttyS5適合作為Master
    ESM6800EttyS1—ttyS6適合作為Master
    ESM6800LttyS1—ttyS6適合作為Slave
    ESM6802ttyS1—ttyS4適合作為Master
    ESM7000ttyS1—ttyS6適合作為Master


      如果要使用9bit RS485模式,需要在程序中進(jìn)行使能,使能后串口就會(huì)進(jìn)入到該模式中,在發(fā)送數(shù)據(jù)的時(shí)候,可以支持兩種方式,一種是發(fā)送地址字節(jié),另一種是發(fā)送數(shù)據(jù)字節(jié)。在接收數(shù)據(jù)字節(jié)的時(shí)候,分為master和slave兩種模式,這兩種模式都需要先接收地址字節(jié),才能夠接收數(shù)據(jù)字節(jié),如果沒有接收到地址字節(jié),會(huì)自動(dòng)將數(shù)據(jù)字節(jié)自動(dòng)全部濾掉。他們的區(qū)別在于master模式下,只要接收到地址字節(jié),就會(huì)將這之后的數(shù)據(jù)字節(jié)全部接收,并交給應(yīng)用程序處理。而在slave模式下,需要先設(shè)置設(shè)備地址,只有接收到的地址字節(jié)和設(shè)備地址相同時(shí),才會(huì)開始接收數(shù)據(jù)字節(jié)。


      master模式下,接收數(shù)據(jù)示意圖:


    RS485網(wǎng)絡(luò)的整幀數(shù)據(jù)收發(fā)-2.png


      Slave模式下,接收數(shù)據(jù)示意圖:


    RS485網(wǎng)絡(luò)的整幀數(shù)據(jù)收發(fā)-3.png


      采用9bit RS485模式,有兩個(gè)優(yōu)點(diǎn),第一點(diǎn)是不需要判斷是否接收到地址字節(jié),因?yàn)榇谝诮邮盏降刂纷止?jié)(校驗(yàn)位為1)后,才會(huì)接收數(shù)據(jù)字節(jié),特別是在slave模式下,只有當(dāng)?shù)刂纷止?jié)和設(shè)置的設(shè)備地址相等時(shí),才會(huì)接收數(shù)據(jù)。第二點(diǎn)是不需要切換校驗(yàn)方式,當(dāng)串口啟用了9bit RS485模式,就可以正常接收所有地址字節(jié)和數(shù)據(jù)字節(jié)了,只有在發(fā)送地址字節(jié)和數(shù)據(jù)字節(jié)的時(shí)候需要切換不同的設(shè)置,可以減少軟件上的操作。


      英創(chuàng)公司在提供的例程Step2_serialtest中封裝的串口類CSerial的基礎(chǔ)上派生出一個(gè)專用于9bit RS485的類CRS485,在這個(gè)類中我們?cè)黾邮鼓?bit RS485模式的函數(shù),讓客戶可以直接調(diào)用來實(shí)現(xiàn)相關(guān)功能。


    /**
     *    派生用于9bit RS485的類
     *
    **/
    class CRS485 : public CSerial
    {
    private:
           //串口模式、設(shè)備地址和接收超時(shí)時(shí)間
           int serial_mode;
           int serial_addr;
     
    public:
           //接收數(shù)據(jù)緩存和長(zhǎng)度
           char frame[100];
           int  frame_len;
     
           /**
            *    派生類的構(gòu)造函數(shù)
            *
            *    在構(gòu)造函數(shù)中初始化變量,以及設(shè)置9-bit RS485模式下的串口是處于master還是slave模式
            *
            *    參數(shù)說明:
            *    mode:值為0對(duì)應(yīng)master模式,值為1對(duì)應(yīng)slave模式
            *    addr:設(shè)備地址,大小為8bit,當(dāng)且僅當(dāng)mode為1是有效。
            *
           **/
           CRS485(int mode, int addr);
     
           /**
            *    發(fā)送9bit RS485整包數(shù)據(jù)
            *
            *    函數(shù)會(huì)將地址字節(jié)和數(shù)據(jù)字節(jié)填寫,并設(shè)置為相應(yīng)的模式一并發(fā)送
            *
            *    參數(shù)說明:
            *    addr:設(shè)備地址,大小為8bit,填入發(fā)送數(shù)據(jù)的地址字節(jié)中
            *    Buf:發(fā)送的數(shù)據(jù)字節(jié)
            *    len:發(fā)送數(shù)據(jù)字節(jié)的長(zhǎng)度
            *
            *    返回值說明:
            *    len:成功
            *    -1:失敗
            *
           **/
           int send_rs485_frame(char addr, char *Buf, int len);
     
           /**
            *    接收9bit RS485整包數(shù)據(jù)
            *
            *    函數(shù)會(huì)阻塞接收指定長(zhǎng)度的數(shù)據(jù),可以設(shè)置超時(shí)時(shí)間,如果超過超時(shí)時(shí)間沒有接收到指定長(zhǎng)度的數(shù)據(jù),則返回-1
            *
            *    參數(shù)說明:
            *    Buf:接收的數(shù)據(jù)字節(jié)
            *    len:發(fā)送數(shù)據(jù)字節(jié)的長(zhǎng)度
            *    timeout:超時(shí)時(shí)間,單位毫秒。如果在超時(shí)時(shí)間內(nèi)沒有收到指定長(zhǎng)度的數(shù)據(jù),則返回-1。值為0則不阻塞,讀取不到數(shù)據(jù)立即返回。值為-1則沒有超時(shí)時(shí)間,如果接受不到指定長(zhǎng)度數(shù)據(jù)會(huì)一直等待
            *
            *    返回值說明:
            *    成功則返回接收到的數(shù)據(jù)長(zhǎng)度
            *    -1:超時(shí)
            *
           **/
           int recv_rs485_frame(char *Buf, int len, int timeout);
     
           /**
            *    繼承自CSerial類的接收處理函數(shù)
            *
            *    在CSerial類的接收線程中會(huì)調(diào)用這個(gè)函數(shù),可以在函數(shù)中調(diào)用recv_rs485_frame()函數(shù),并處理接收到的數(shù)據(jù)字節(jié)
            *     
            *
           **/
           int PackagePro();
    };


      在類實(shí)例化的時(shí)候,代入?yún)?shù)就可以決定串口是處于master模式還是slave模式,如果是出于slave模式可以一起代入需要設(shè)定的設(shè)備地址:


    //master模式
    class CRS485  m_Serial(0, 0);
     
    //slave模式,設(shè)備地址為0x55
    class CRS485  m_Serial(1, 0x55);



      接收處理的時(shí)候,數(shù)據(jù)的長(zhǎng)度通過宏DATA_LEN定義,客戶可以在PackagePro()函數(shù)中可以定義超時(shí)時(shí)間,然后調(diào)用recv_rs485_frame()函數(shù)來接收整包數(shù)據(jù),recv_rs485_frame()函數(shù)會(huì)阻塞,直至收到指定長(zhǎng)度的數(shù)據(jù),或者到達(dá)超時(shí)時(shí)間才會(huì)返回。接收到整包數(shù)據(jù)后,就可以開始進(jìn)行數(shù)據(jù)的處理,在接收線程調(diào)中循環(huán)調(diào)用PackagePro函數(shù):


    #define DATA_LEN 10                    // 數(shù)據(jù)長(zhǎng)度
     
    // 接收串口數(shù)據(jù)處理函數(shù)
    int CRS485::PackagePro()
    {
           int i1, timeout;
     
           //設(shè)置超時(shí)時(shí)間,單位毫秒
           timeout = 500;
     
           //調(diào)用接收函數(shù)來獲取指定長(zhǎng)度的整包數(shù)據(jù)
           i1 = recv_rs485_frame(DatBuf, m_DatLen, timeout);
     
           //接收到整包數(shù)據(jù),調(diào)用處理程序,這里只是簡(jiǎn)單的打印
           if(i1 != -1)
           {
                  printf("frame addr = 0x%x\n", frame[0]);
                  printf("frame data = ");
                  for(i1=1; i1<DATA_LEN; i1++) {
                         printf("0x%x ", frame[i1]);
                  }
                  printf("\n");
     
                  //處理完數(shù)據(jù),清除各個(gè)變量,重新設(shè)置串口以等待下一包數(shù)據(jù)
                  memset(frame, 0, 100);
                  frame_len = 0;
           }
           else
                  printf("time out!\n");
     
           return i1;
    }


      在線程中的處理,循環(huán)調(diào)用接收處理函數(shù)即可,因?yàn)閞ecv_rs485_frame()函數(shù)會(huì)阻塞,直至收到指定長(zhǎng)度的數(shù)據(jù),或者到達(dá)超時(shí)時(shí)間才會(huì)返回:


    int CSerial::ReceiveThreadFunc(void* lparam)
    {
           CSerial *pSer = (CSerial*)lparam;
     
           //定義讀事件集合
           fd_set fdRead;
           int ret;
           struct timeval     aTime;
     
           while( 1 )
           {
                  //接收處理函數(shù)
                  pSer->PackagePro( pSer->DatBuf, pSer->m_DatLen);
     
           }
     
           printf( "ReceiveThreadFunc finished\n");
           pthread_exit( NULL );
           return 0;
    }



      串口在發(fā)送的時(shí)候,比較簡(jiǎn)單,直接調(diào)用send_rs485_frame()函數(shù),填入需要發(fā)送的地址和數(shù)據(jù)即可,使用下面的代碼來測(cè)試:


    char        addr = 0x55;
    char    Buf[2];
     
    Buf[0] = 0x55;
    Buf[1] = 0xaa;
     
    //發(fā)送地址字節(jié)和數(shù)據(jù)字節(jié)
    m_Serial.send_rs485_frame(addr, Buf, sizeof(Buf));


      主板實(shí)際輸出的波形如下:


    RS485網(wǎng)絡(luò)的整幀數(shù)據(jù)收發(fā).png


      感興趣的客戶可以和英創(chuàng)的工程師聯(lián)系,索取完整的測(cè)試工程。

    无码国产69精品久久久久网站| 中文成人无码精品久久久不卡| 国产乱人伦偷精品视频下| 国产成人精品综合久久久| 国产精品无码AV一区二区三区| 亚洲国产精品久久丫| 9999国产精品欧美久久久久久| 精品国产毛片一区二区无码 | 亚洲精品第五页中文字幕 | 老司机福利精品视频| 日本精品久久久久中文字幕8| 国产福利微拍精品一区二区| 国产午夜亚洲精品不卡| 国产精品久久99| 精品人妻一区二区三区毛片| 国产精品无码免费播放| 国产精品亚洲A∨天堂不卡| 日韩精品专区在线影院重磅| 99re这里只有精品6| 一本精品中文字幕在线| 亚洲精品无码久久久久| 国产午夜亚洲精品| 亚洲热线99精品视频| sss视频在线精品| 精品国产一区二区三区色欲| 女人香蕉久久**毛片精品| 亚洲国产精品成人| 国产精品大片天天看片| 99精品久久99久久久久久| 亚洲国产精品人人做人人爽| 99精品全国免费观看视频| 久久精品桃花综合| 国产福利91精品一区二区| 98精品全国免费观看视频| 国产99精品一区二区三区免费| 成人精品视频一区二区三区尤物| 久久久久se色偷偷亚洲精品av| 中文字幕日韩专区精品系列| 中文无码精品A∨在线观看不卡| 1313午夜精品理伦片| 久久精品无码午夜福利理论片|