2014-12-30 164 views
0

我有一個應用程序在windows上運行,它將通過串口發送數據。 下面是代碼:通過串口發送和接收Windows

m_hCommPort= ::CreateFile(L"\\\\.\\COM3", 
     GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING,0,0); 

    if(m_hCommPort == INVALID_HANDLE_VALUE) 
    { 
     printf("COM error: %d\n", GetLastError()); 
    } 
    config.DCBlength = sizeof(config); 


    if((GetCommState(m_hCommPort, &config) == 0)) 
    { 
     CloseHandle(m_hCommPort); 
     printf("Get configuration port has a problem.\n"); 
     return FALSE; 
    } 

    config.BaudRate = 9600; 
    config.StopBits = ONESTOPBIT; 
    config.Parity = PARITY_NONE; 
    config.ByteSize = DATABITS_8; 
    config.fDtrControl = 0; 
    config.fRtsControl = 0; 

    if (!SetCommState(m_hCommPort, &config)) 
    { 
     CloseHandle(m_hCommPort); 
     printf("Failed to Set Comm State Reason: %d\n",GetLastError()); 
     return E_FAIL; 
    } 

這裏是只發送(工作)的代碼(連續發送)

while(1) 
    { 
     Sleep(5000); 
     int isWritten = WriteFile(m_hCommPort, txData, 9/*(DWORD)sizeof(txData)*/, &dwBytesWritten, NULL); 
      printf("isWritten: %d, dwBytesWritten: %d \n", isWritten, dwBytesWritten); 

    } 

這個我已經添加代碼接收數據量太大,則發送不工作後。我的意思是無法通過UART發送數據。 WriteFile()似乎沒有執行,它卡住了。 在這裏我添加了一個線程來接收數據,是線程導致的問題?還是我需要做別的事情?

void ReceiverThread(void *param) 
{ 
    DWORD dwRead=0; 
    BOOL fWaitingOnRead = FALSE; 
    OVERLAPPED osReader = {0}; 

    osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 

    if (osReader.hEvent == NULL) 
     printf("Error creating overlapped event; abort.\n"); 
    while(1) 
    { 
     if (!ReadFile(m_hCommPort, &Byte, 1, &dwRead, &osReader)) { 
      if (GetLastError() != ERROR_IO_PENDING)  // read not delayed? 
       printf("Error in communications; report it.\n"); 
      else 
       fWaitingOnRead = TRUE; 
     } 
     else {  

      rxData[rxHeadIndex++]= Byte; 
      rxHeadIndex = (rxHeadIndex) & QUEUE_MASK; 
     } 


    } 

} 


SetCommMask (m_hCommPort, EV_RXCHAR/ | EV_ERR); //receive character event 


    _beginthread(ReceiverThread,0,NULL); 


    while(1) 
    { 
     Sleep(5000); 
     int isWritten = WriteFile(m_hCommPort, txData, 9/*(DWORD)sizeof(txData)*/, &dwBytesWritten, NULL); 
      printf("isWritten: %d, dwBytesWritten: %d \n", isWritten, dwBytesWritten); 

    } 

在此先感謝。 Ashok

回答

2

前段時間我遇到過類似的問題。

我發現WriteFile(..)塊如果一個ReadFile(..)目前正在進行串口。所以這是一個問題,如果ReadFile(..)阻塞,如果沒有數據要讀取。

我已經解決了這個問題,通過檢查串口緩衝區內是否有數據可以通過使用函數ClearCommError(..)來讀取。這確保ReadFile(..)可以立即讀取某些內容並且不會不必要地阻塞該設備。試着改變你的ReceiverThread弄成這個樣子:

void ReceiverThread(void *param) 
{ 
    DWORD dwRead=0; 
    COMSTAT comStat; 
    char buffer[1024]; 

    while (m_hCommPort != INVALID_HANDLE_VALUE) 
    { 
     if ((ClearCommError(m_hCommPort, NULL, &comStat) != FALSE) && (comStat.cbInQue > 0)) 
     { 
      /* todo: ensure buffer is big enough to contain comStat.cbInQue bytes! */ 

      if (ReadFile(m_hCommPort, buffer, comStat.cbInQue, &dwRead, NULL) != FALSE) 
      { 
       /* do something with data in buffer */ 
      } 
     } 

     /* avoid busy-wait */ 
     if (comStat.cbInQue == 0) 
     { 
      SleepEx(1, FALSE); 
     } 
    } 
} 

這樣ReadFile(..)如果數據是可用的,同時WriteFile(..)可以在不被封鎖發送數據時纔會調用。

不幸的是,我一直無法使ClearCommError(..)阻塞,所以我使用了SleepEx(1, FALSE);解決方法來避免忙碌的等待,因此最好ReceiverThread吃掉了CPU。

+0

感謝您的幫助。我會試試這個,讓你知道結果。 – Ashok

+0

其工作但接收緩衝區應處理其他部分if(!ReadFile(m_hCommPort,buffer,comStat.cbInQue,&dwRead,NULL))。 – Ashok

+0

@Asht Houups,當然可以!我改變了原來的帖子......感謝您指出了這一點。 –

1
config.fDtrControl = 0; 
    config.fRtsControl = 0; 

這些設置關閉DTR和RTS握手線。大多數串行設備都關注這些信號。假設機器未通電,它們將不會在您的DTR信號關閉時發送任何內容。假設機器沒有準備好接收任何數據,並且在RTS信號關閉時不會發送任何內容。

所以你觀察到的是完全正常的。

由於設備看起來是「正常」,並且確實注意握手線,所以您需要配置DCB以讓設備驅動程序自動控制這些信號。修復:

config.fDtrControl = DTR_CONTROL_ENABLE; 
    config.fRtsControl = RTS_CONTROL_HANDSHAKE; 

此外,終端仿真程序,如膩子和超級終端的默認值。首先使用這樣的程序來確保接線和設備的功能。如果您無法獲取任何設備數據以顯示在此類程序中,那麼它也不適用於您的程序。如果全部檢出,則還要將fDsrSensitivity,fOutxCtsFlow和fOutxDsrFlow屬性設置爲TRUE,以便您將轉而關注設備的握手信號。