2014-12-30 126 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,以便您将转而关注设备的握手信号。