2014-12-30 2 views
0

У меня есть приложение, работающее на окнах, которое будет отправлять данные через последовательный порт. Вот код:отправлять и получать через последовательный порт 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); обходные, чтобы избежать занят, подождите, и поэтому prefenting в ReceiverThread съесть процессор.

+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; 

Также по умолчанию для терминальных эмуляторов, таких как Putty и HyperTerminal. Сначала используйте такую ​​программу, чтобы обеспечить правильную работу проводки и устройства. Если вы не можете получить какие-либо данные устройства, которые будут отображаться в такой программе, это также не будет работать с вашей программой. Если все это проверяется, то также установите для свойств fDsrSensitivity, fOutxCtsFlow и fOutxDsrFlow значение TRUE, чтобы вы, в свою очередь, обращали внимание на сигналы подтверждения связи устройства.

Смежные вопросы