激情综合丁香-激情综合六月-激情综合婷婷亚洲图片-激情综合图区-激情综合网五月

RS485接口通訊的WinCE編程要點

 2009-9-27              

        在工業控制場合,RS485總線因其接口簡單,組網方便,傳輸距離遠等特點而得到廣泛應用。RS485和RS232一樣都是基于串口的通訊接口,數據收發的操作是一致的,所以使用的是同樣WinCE的底層驅動程序。但是它們在實際應用中通訊模式卻有著很大的區別,RS232接口為全雙工數據通訊模式,而RS485接口為半雙工數據通訊模式,數據的收發不能同時進行,為了保證數據收發的不沖突,硬件上是通過方向切換來實現的,相應也要求軟件上必須將收發的過程嚴格地分開。WinCE是一個多線程實時操作系統,RS232通信數據收發可在不同線程中同時進行,而對于RS485就不能采用這種方式,必須按照一定的流程來實現RS485所要求的通訊過程。大多數的RS485通訊采用主從通訊方式,在本文中將以電力系統中常用的DL/T 645多功能電能表通信規約為例,來說明RS485半雙工通訊的WinCE編程要點。

        本例通過封裝兩個類來實現DL645通信規約,一、用于串口通信的CESerial類,完成打開、關閉串口,收發串口數據等功能。二、實現DL645規約鏈路層的類DL645_LCP,它提供設置通信地址,超時時間等信息,并完成通信幀的打包、解包、錯誤較驗、數據幀收發的功能。

        基于485半雙工通信的特點,使用一個函數Transmit()來完成數據收發。在調用Transmit()函數發送數據后,程序并不立即返回,而是等待數據接收。一個完整的數據發送\接收過程如下:
        ·應用層調用DL645_LCP類的Transmit()方法,并將發送的數據傳遞給Transmit()。
        ·在Transmit()方法中對數據打包,增加幀起始符,幀結束符,校驗碼等信息,使其符合DL645規約。
        ·調用串口通信CESerial類的WritePort()方法函數,發送一幀數據。
        ·等待數據接收。遇下列情況之一時,函數返回:1、接收到一幀完整數據,2、接收超時,3、較驗出錯,4、通信出錯。

        下面是Transmit()函數的源代碼:

int DL645_LCP::Transmit( LPSTR pDat, int DLen )
{
        int i1, i2;
        UCHAR WBuf[MaxWDatLen];
        // fill write data
        for( i1=0; i1<4; i1++ )
                WBuf[i1] = 0xFE;
        WBuf[i1] = 0x68;
        i1++;
        memcpy( &WBuf[i1], &m_LAddr, 6 );
        i1 += 6;
        WBuf[i1] = 0x68; 
        i1++;
        memcpy( &WBuf[i1], pDat, 2 );
        i1 += 2;
        for( i2=2; i2 < Dlen; i2++)
        {
                WBuf[i1] = pDat[i2] + 0x33;
                i1++;
        }
        WBuf[i1] = GetCS( &WBuf[4], i1-4 );
        i1++;
        WBuf[i1] = 0x16;
        i1++;
        // write data
        m_nDatLen = 0;
        m_nDatErrFlg = 0;
        m_nUserDatLen = 0;
        m_state = RevStateIDLE;
        // 發送一幀數據
        ceSer.WritePort( (LPSTR)WBuf, i1 );
        SetTimeOut( m_dwTimeOut );
        // 等待數據接收
        for(;;)
        {
                if( IsTimeOut() )
                        return ErrTimeout; // 接收超時返回
                else if( m_nDatErrFlg == 1 )
                        return -2; // 數據出錯返回
                else if( m_state == RevStateEND ) // 數據接收完成返回
                {
                        memcpy( pDat, &RBuf[8], m_nDatLen-8-2 );
                        return m_nUserDatLen;
                }
                else
                {
                        Sleep( 5 );
                }
        }
}

        數據接收時,CESerial類的中斷處理函數收到數據,直接調用DL645_LCP類中的Receive()方法,在Receive()函數中完成一幀數據的解包工作。

void DL645_LCP::Receive( )
{
        UINT i, i1;
        if( m_nDatLen <= MaxRDatLen )
        {
                for( i=0; i
                {
                        SetTimeOut( m_dwTimeOut );
                        RBuf[m_nDatLen] = (unsigned char)ceSer.DatBuf[i];
                        switch( m_state )
                        { 
                        case RevStateIDLE:
                                if( RBuf[m_nDatLen]==0x68 )
                                {
                                        m_state = RevStateSTART;
                                        m_nDatLen++;
                                }
                                break; 
                        case RevStateSTART:
                                m_nDatLen++;
                                if( m_nDatLen==7 ) m_state = RevStateADDR;
                                break; 
                        case RevStateADDR:
                                if( RBuf[m_nDatLen]==0x68 )
                                {
                                        m_state = RevStateSTART1;
                                        m_nDatLen++;
                                }
                                break;
                        case RevStateSTART1:
                                m_nDatLen++;
                                m_state = RevStateCTRL;
                                break;
                        case RevStateCTRL:
                                m_nUserDatLen = RBuf[m_nDatLen]; 
                                if( m_nUserDatLen==0 ) m_state = RevStateDATA;
                                else m_state = RevStateDLEN;
                                m_nDatLen++;
                                break;
                        case RevStateDLEN:
                                m_nDatLen++;
                                if( m_nDatLen==(10+m_nUserDatLen) )
                                        m_state = RevStateDATA;
                                break;
                        case RevStateDATA:
                                m_state = RevStateSUM; 
                                if( GetCS( RBuf, m_nDatLen)!= RBuf[m_nDatLen] )
                                        m_nDatErrFlg = 1;
                                m_nDatLen++;
                                break;
                        case RevStateSUM:
                                if( RBuf[m_nDatLen]==0x16 )
                                {
                                        m_nDatLen++;
                                        for( i1=0; i1RBuf[10+i1] -= 0x33;
                                                m_state = RevStateEND;
                                }
                                break; 
                        default:;
                        }
                }
        }
        else m_nDatErrFlg = 1;
}

        利用本文提供的例程,在DL645_LCD類上做相應的修改,可方便的實現其它的485通信規約。

主站蜘蛛池模板: 日韩毛片在线| 黄色国产在线视频| 小色片| 免费手机黄色网址| 特一级黄色毛片| 天天色综合三| 小毛片在线观看| 中文字幕爱爱| 免费国产成人高清在线观看不卡 | a国产精品| 日本护士xxxxx极品| a级毛片免费在线观看| 永久在线视频| 免费看黄色小视频| 国产福利区一区二在线观看| 成人在线视频国产| 免费观看欧美成人1314色| 国内不卡1区2区| 最新精品视频在线观看| 久久精品国产精品亚洲| 色婷在线| 涩色婷婷狠狠第四四房社区奇米| 好爽好深好猛好舒服视频上| 亚洲第一综合网站| 一区二区三区四区视频在线| 手机日韩看片| 色盈盈影院| 欧美一级毛片激情| 国产成人免费在线观看| 黄色网页视频| 婷婷色视频| 国产不卡一区二区三区免费视| 欧美在线 | 亚洲| 亚洲自拍激情| 一区二区三区四| 一级骚片| 日本亚洲国产| 可以看黄色的网站| 网址在线| 欧美日本一本| 国产一级爱c片免费观看|