• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • VC++ 的串口通訊

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    在VC++中有兩種方法可以進行串口通訊。一種是利用Microsoft公司提供的ActiveX控件 Microsoft Communications Control。另一種是直接用VC++訪問串口。下面將簡述這兩種方法。 一、Microsoft Communications Control Microsoft公司在 WINDOWS 中提供了一個串口
    在VC++中有兩種方法可以進行串口通訊。一種是利用Microsoft公司提供的ActiveX控件 Microsoft Communications Control。另一種是直接用VC++訪問串口。下面將簡述這兩種方法。

      一、Microsoft Communications Control

      Microsoft公司在WINDOWS中提供了一個串口通訊控件,用它,我們可以很簡單的利用串口進行通訊。在使用它之前,應將控件加在應用程序的對話框上。然后再用ClassWizard 生成相應的對象?,F在我們可以使用它了。

      該控件有很多自己的屬性,你可以通過它的屬性窗口來設置,也可以用程序設置。我推薦用程序設置,這樣更靈活。

       SetCommPort:指定使用的串口。

       GetCommPort:得到當前使用的串口。

       SetSettings:指定串口的參數。一般設為默認參數"9600,N,8,1"。這樣方便與其他串口進行通訊。

       GetSettings:取得串口參數。

       SetPortOpen:打開或關閉串口,當一個程序打開串口時,另外的程序將無法使用該串口。

       GetPortOpen:取得串口狀態。

       GetInBufferCount:輸入緩沖區中接受到的字符數。

       SetInPutLen:一次讀取輸入緩沖區的字符數。設置為0時,程序將讀取緩沖區的全部字符。

       GetInPut:讀取輸入緩沖區。

       GetOutBufferCount:輸出緩沖區中待發送的字符數。

       SetOutPut:寫入輸出緩沖區。

      一般而言,使用上述函數和屬性就可以進行串口通訊了。以下是一個范例。

    #define MESSAGELENGTH 100

    class CMyDialog : public CDialog
    {
    protected:
    VARIANT InBuffer;
    VARIANT OutBuffer;
    CMSComm m_Com;
    public:
    ......
    }

    BOOL CMyDiaLog::OnInitDialog()
    {
    CDialog::OnInitDialog();
    m_Com.SetCommPort(1);
    if (!m_Com.GetPortOpen()) {
    m_Com.SetSettings("57600,N,8,1");
    m_Com.SetPortOpen(true);
    m_Com.SetInBufferCount(0);
    SetTimer(1,10,NULL);
    InBuffer.bstrVal=new unsigned short[MESSAGELENGTH];
    OutBuffer.bstrVal=new unsigned short[MESSAGELENGTH];
    OutBuffer.vt=VT_BSTR;
    }
    return true;
    }

    void CMyDiaLog::OnTimer(UINT nIDEvent)
    {
    if (m_Com.GetInBufferCount()>=MESSAGELENGTH) {
    InBuffer=m_Com.GetInput();
    // handle the InBuffer.
    // Fill the OutBuffer.
    m_Com.SetOutput(OutBuffer);
    }
    CDialog::OnTimer(nIDEvent);
    }



      用該控件傳輸的數據是UNICODE格式。關于UNICODE和ANSI的關系和轉換請參看MSDN。

      關于該控件的其他詳細資料請查看MSDN關于COMM CONTROL部分。

      二、直接用VC++訪問串口。

      在VC++中,串口和磁盤文件可以統一的方式來簡單讀寫。這兩者幾乎沒有什么不同,只是在WINDOWS 9X下磁盤文件只能做同步訪問,而串口只能做異步訪問。

      CreateFile:用指定的方式打開指定的串口。通常的方式為

      m_hCom = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );

      m_hCom為文件句柄。GENERIC_READ | GENERIC_WRITE指定可以對串口進行讀寫操作。第三個參數0表示串口為獨占打開。OPEN_EXISTING表示當指定串口不存在時,程序將返回失敗。 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED則表示文件屬性。當打開串口時,必須指定 FILE_FLAG_OVERLAPPED,它表示文件或設備不會維護訪問指針,則在讀寫時,必須使用OVERLAPPED 結構指定訪問的文件偏移量。

       ReadFile:讀取串口數據。

       WriteFile:向串口寫數據。

       CloseHandle:關閉串口。

      COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超時參數設置。COMMTIMEOUTS結構如下:

    typedef struct _COMMTIMEOUTS {
    DWORD ReadIntervalTimeout;
    DWORD ReadTotalTimeoutMultiplier;
    DWORD ReadTotalTimeoutConstant;
    DWORD WriteTotalTimeoutMultiplier;
    DWORD WriteTotalTimeoutConstant;
    } COMMTIMEOUTS,*LPCOMMTIMEOUTS;


      ReadIntervalTimeout:兩字符之間最大的延時,當讀取串口數據時,一旦兩個字符傳輸的時間差超過該時間,讀取函數將返回現有的數據。設置為0表示該參數不起作用。

      ReadTotalTimeoutMultiplier:讀取每字符間的超時。

      ReadTotalTimeoutConstant:一次讀取串口數據的固定超時。所以在一次讀取串口的操作中,其超時為ReadTotalTimeoutMultiplier乘以讀取的字節數再加上 ReadTotalTimeoutConstant。將ReadIntervalTimeout設置為MAXDWORD,并將ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant設置為0,表示讀取操作將立即返回存放在輸入緩沖區的字符。

      WriteTotalTimeoutMultiplier:寫入每字符間的超時。

      WriteTotalTimeoutConstant:一次寫入串口數據的固定超時。所以在一次寫入串口的操作中,其超時為WriteTotalTimeoutMultiplier乘以寫入的字節數再加上 WriteTotalTimeoutConstant。

      SetCommTimeouts函數可以設置某設備句柄的超時參數,要得到某設備句柄的超時參數可以用GetCommTimeouts函數。

      DCB:DCB結構主要用于串口參數設置。該結構太龐大,這里就不一一講述了,有興趣者可查看MSDN關于DCB的描述。其中下面兩個是比較重要的屬性。

      BaudRate:串口的通訊速度。一般設置為9600。

      ByteSize:字節位數。一般設置為8。

      DCB結構可以用SetCommState函數來設置,并可以用GetCommState來得到現有串口的屬性。

      SetupComm:設置串口輸入、輸出緩沖區。

      OVERLAPPED:保存串口異步通訊的信息。具體結構如下:

    typedef struct _OVERLAPPED {
    DWORD Internal;
    DWORD InternalHigh;
    DWORD Offset;
    DWORD OffsetHigh;
    HANDLE hEvent;
    } OVERLAPPED;


      Internal,InternalHigh是保留給系統使用的,用戶不需要設置。

      Offset,OffsetHigh是讀寫串口的偏移量,一般設置OffsetHigh為NULL,可以支持2GB數據。

      hEvent讀寫事件,因為串口是異步通訊,操作可能被其他進程堵塞,程序可以通過檢查該時間來得知是否讀寫完畢。事件將在讀寫完成后,自動設置為有效。

      通過以上這些函數和結構,我們就可以通過串口進行通訊了,現在我們具體看下面的實例:

    BOOL CSerial::Open( int nPort, int nBaud )
    {
    if( m_bOpened ) return( TRUE );

    char szPort[15];
    DCB dcb;

    wsprintf( szPort, "COM%d", nPort );
    m_hComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
    if( m_hComDev == NULL ) return( FALSE );

    memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
    memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

    COMMTIMEOUTS CommTimeOuts;
    CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
    CommTimeOuts.ReadTotalTimeoutConstant = 0;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    CommTimeOuts.WriteTotalTimeoutConstant = 5000;
    SetCommTimeouts( m_hComDev, &CommTimeOuts );

    m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

    dcb.DCBlength = sizeof( DCB );
    GetCommState( m_hComDev, &dcb );
    dcb.BaudRate = nBaud;
    dcb.ByteSize = 8;
    if( !SetCommState( m_hComDev, &dcb ) ||
    !SetupComm( m_hComDev, 10000, 10000 ) ||
    m_OverlappedRead.hEvent == NULL ||
    m_OverlappedWrite.hEvent == NULL ){
    DWORD dwError = GetLastError();
    if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
    if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
    CloseHandle( m_hComDev );
    return FALSE;
    }

    m_bOpened = TRUE;

    return m_bOpened;

    }

    int CSerial::InBufferCount( void )
    {

    if( !m_bOpened || m_hComDev == NULL ) return( 0 );

    DWORD dwErrorFlags;
    COMSTAT ComStat;

    ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );

    return (int)ComStat.cbInQue;

    }

    DWORD CSerial::ReadData( void *buffer, DWORD dwBytesRead)
    {

    if( !m_bOpened || m_hComDev == NULL ) return 0;

    BOOL bReadStatus;
    DWORD dwErrorFlags;
    COMSTAT ComStat;

    ClearCommError( m_hComDev, &dwErrorFlags, &ComStat );
    if( !ComStat.cbInQue ) return 0;

    dwBytesRead = min(dwBytesRead,(DWORD) ComStat.cbInQue);

    bReadStatus = ReadFile( m_hComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
    if( !bReadStatus ){
    if( GetLastError() == ERROR_IO_PENDING ){
    WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
    return dwBytesRead;
    }
    return 0;
    }

    return dwBytesRead;

    }

    DWORD CSerial::SendData( const char *buffer, DWORD dwBytesWritten)
    {

    if( !m_bOpened || m_hComDev == NULL ) return( 0 );

    BOOL bWriteStat;

    bWriteStat = WriteFile( m_hComDev, buffer, dwBytesWritten, &dwBytesWritten, &m_OverlappedWrite );
    if( !bWriteStat){
    if ( GetLastError() == ERROR_IO_PENDING ) {
    WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 );
    return dwBytesWritten;
    }
    return 0;
    }
    return dwBytesWritten;

    }



      上述函數基本實現串口的打開,讀寫操作。本文章略去該串口類的說明和關閉函數。讀者應該能將這些內容寫完。接下來,你就可以在你的程序中調用該串口類了。關于本文有任何疑問,請與作者聯系。

      本文參考文獻:MSDN 1999, Microsoft Corp

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>