// 写函数
int CRead_MaterDlg::WriteCom(DWORD m_length)
{
  COMSTAT ComStat;
  DWORD dwBytesSent=0;
  DWORD dwErrorFlags;
  DWORD dwBytesWrite;
  DWORD dwError=0;
  OVERLAPPED Write_Os;
  Write_Os.Offset=0;
  Write_Os.OffsetHigh=0;
  Write_Os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  DWORD fWriteStat;
  fWriteStat = WriteFile(hCom,lpSendBuffer,m_length,&dwBytesWrite,&Write_Os);  
  if (!fWriteStat)
 { 
if(GetLastError() == ERROR_IO_PENDING)

while(!GetOverlappedResult(hCom,&Write_Os,
                         &dwBytesWrite,TRUE))

 dwError = GetLastError();
         if(dwError == ERROR_IO_INCOMPLETE)
             {
    dwBytesSent+=dwBytesWrite;
           continue;
    }
          else
{
ClearCommError(hCom,&dwErrorFlags,&ComStat);
break;
}

dwBytesSent+=dwBytesWrite;
}
else
ClearCommError(hCom,&dwErrorFlags,&ComStat);
 }
        else
dwBytesSent+=dwBytesWrite;
  CloseHandle(Write_Os.hEvent);
  return dwBytesSent;
}// 读串口数据函数
int CRead_MaterDlg::readcom()

  
  ASSERT(hCom);
  // 缓冲区中有数据到达 
  COMSTAT ComStat;
  DWORD dwLength;
  DWORD dwErrorFlags;
  DWORD dwBytesRead=0;
  DWORD dwError=0;
  OVERLAPPED Read_Os;
  Read_Os.Offset=0;
  Read_Os.OffsetHigh=0;
  Read_Os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  ClearCommError(hCom,&dwErrorFlags,&ComStat); 
  // 输入缓冲区有多少数据?
  dwLength = ComStat.cbInQue; 
  if(dwLength > 0) 
    { 
    DWORD fReadStat;
    //读数据
    fReadStat = ReadFile(hCom,lpRecieveBuffer,dwLength,
                 &dwLength,&Read_Os);  
   if (!fReadStat)
      { 
       if(GetLastError() == ERROR_IO_PENDING)

while(!GetOverlappedResult(hCom,&Read_Os,
                   &dwLength,TRUE))

dwError = GetLastError();
        if(dwError == ERROR_IO_INCOMPLETE)
{
dwBytesRead+=dwLength;
         continue;
}
else
{
ClearCommError(hCom,&dwErrorFlags,&ComStat);
break;
}

dwBytesRead+=dwLength;
}
else
ClearCommError(hCom,&dwErrorFlags,&ComStat);
}
       else
dwBytesRead+=dwLength;
}
  else
  ClearCommError(hCom,&dwErrorFlags,&ComStat);
  CloseHandle(Read_Os.hEvent);
  return dwBytesRead;
}
//  线程过程
UINT CRead_MaterDlg::CommWatchProc(LPVOID pParam)
{
DWORD dwEvtMask=0;
DWORD mError;
DWORD mwaitflags;
OVERLAPPED Os;
Os.Offset=0;
Os.OffsetHigh=0;
Os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
// 等待串口通信事件的发生
while(ThreadStop)
{
mwaitflags=WaitCommEvent(hCom,&dwEvtMask,&Os);
mError=GetLastError();
if(mError==ERROR_IO_PENDING)
mwaitflags=(WaitForSingleObject(Os.hEvent,0)     
               ==WAIT_OBJECT_0);
if(mwaitflags>0)
   ResetEvent(Os.hEvent);
}
CloseHandle(Os.hEvent);
PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT |   
                    PURGE_TXCLEAR | PURGE_RXCLEAR);  
return 1;
}
线程我是在初始化时创建的(afxbeginthread());为何我写后,再读老是慢一拍呢????

this->WriteCom();
Sleep(100);
this->readcom();
为何啊!请多多指教。还有怎么能把cstring类型转换为float类型呢??多谢!!

解决方案 »

  1.   

    UINT CSerialPort::CommThread(LPVOID pParam)
    { CSerialPort *port = (CSerialPort*)pParam;

    port->m_bThreadAlive = TRUE;

    DWORD BytesTransfered = 0; 
    DWORD Event = 0;
    DWORD CommEvent = 0;
    DWORD dwError = 0;
    COMSTAT comstat;
    BOOL  bResult = TRUE;
    DWORD ByteRead;

    if (port->m_hComm) // check if the port is opened
    PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); for (;;) 
    {  bResult = WaitCommEvent(port->m_hComm, &CommEvent, &port->m_ov); if (!bResult)  

    switch (dwError = GetLastError()) 

    case ERROR_IO_PENDING: 

    break;
    }
    case 87:
    {
    // Under Windows NT, this value is returned for some reason.
    // I have not investigated why, but it is also a valid reply
    // Also do nothing and continue.
    break;
    }
    default:
    {
    port->ProcessErrorMessage("WaitCommEvent()");
    break;
    }
    }
    }
    else
    {
    bResult = ClearCommError(port->m_hComm, &dwError, &comstat); if (comstat.cbInQue == 0)
    continue;
    } // end if bResult // Main wait function.  This function will normally block the thread
    // until one of nine events occur that require action.
    Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE); switch (Event)
    {
    case 0://exit
    {
                                }
                      case 1://// read event
                               {
                               }
                      case 2: // write event
    {
    WriteChar(port);
    break;
    } } // end switch } // close forever loop return 0;
    }
      

  2.   

    能否解释一下waitforsingleobject和WaitForMultipleObjects的区别和用法吗,我的写法哪个地方出错了,假如我不用该线程监视,只用异步读写,在异步读和写之间sleep(3000)后,它才能读写正确,怎么改善???又为何呢??我的外部设备没怎么慢啊????
      

  3.   

    1200,n,8,1 方式下 58 字节要 1000ms  你的设置呢?
      

  4.   

    但是我的是9600的啊,我想问一下,CString 转换到 Float是否要自己写转换函数啊???
      

  5.   

    CString 转换到 Float: 不用自已写,用atof(str);另外通讯慢可能是不一定是因为你程序慢,有可能是给你回送数据的设备慢!
      

  6.   

    三秒钟才能读出来,肯定是你的外部设备慢根据我的经验,我使用斯赖得最烂的modicon neza plc,modbus协议,19200,n,8,1,一般的数据30byte之内,tx之后50ms就可以rx了,如果数据量很大(如100byte以上,当然,每次发送与接收的数据量都小于256byte,这是mosbus规约所限)200ms足够了。我还测试过看这个plc最快什么时候能够反应过来,结果证实延时25ms的时候,通信开始不可靠,并不是每次发送之后plc都能回应。所以我使用50ms的延时,实践证明是可行的。你用9600bps,速度也不会慢到那里去,单纯数据的发送与接收都是很快的,发送48个字节所需的时间为48*10/9600 = 50ms