初始化部分 
DCB dcb;
   COMMTIMEOUTS TimeOuts;
   hComDev=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
   if(hComDev==INVALID_HANDLE_VALUE) 
   {

   AfxMessageBox("串口错误");
   }
   SetupComm(hComDev,1024,1024);   
   GetCommState(hComDev,&dcb);
   dcb.BaudRate=CBR_9600;
   dcb.fParity=NOPARITY;
   dcb.ByteSize=8;
   dcb.StopBits=ONESTOPBIT;
SetCommMask(hComDev,EV_ERR|EV_RXCHAR);
   PurgeComm(hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
   SetCommState(hComDev,&dcb);
    TimeOuts.ReadIntervalTimeout=0xFFFFFFFF; 
TimeOuts.ReadTotalTimeoutMultiplier=0; 
TimeOuts.ReadTotalTimeoutConstant=1000; 
TimeOuts.WriteTotalTimeoutMultiplier=2*9600/dcb.BaudRate ; 
TimeOuts.WriteTotalTimeoutConstant=25;
   SetCommTimeouts(hComDev,&TimeOuts);
   CEdit*edt1=(CEdit*)GetDlgItem(IDC_EDIT2);
   SetCommMask( hComDev, EV_RXCHAR );
   m_pThread=AfxBeginThread(CommProc,(LPVOID)edt1, THREAD_PRIORITY_NORMAL, 0,0, NULL);
线程读数据部分
UINT CommProc(LPVOID pParam)
{
DWORD       dwEvtMask ;
DWORD length;
char buf[200]={0};
CString sss;
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED   m_osRead={0};
// SetCommMask( hComDev, EV_RXCHAR );

for( ; ;)
{
char buf[200]={0};
dwEvtMask = 0;
WaitCommEvent( hComDev, &dwEvtMask, NULL );
  if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
  {    
ClearCommError(hComDev,&dwErrorFlags,&ComStat);
length=min(255, ComStat.cbInQue);
 if(length > 0)
  {
 m_osRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); 
ReadFile(hComDev,buf,length,&length,&m_osRead);
if(WaitForSingleObject(m_osRead.hEvent,3000)==WAIT_TIMEOUT);
// Sleep(500);
sss.Format("%s",buf);
CEdit*ed=(CEdit*)pParam;
ed->SetWindowText(sss);

  }
return (UINT)0;
}
现在显示读回的数据始终不对,数据不是一次被都会的,尔是几次读回的,我是想一次读回缓冲区的数据,
如果去掉WaitForSingleObject函数,用延时数据分两次被读回,第一次读回前8个字节,第二次读回剩余的字节

解决方案 »

  1.   

    不是缓冲区的问题,而是你使用了非阻塞IO,ReadFile马上返回了而不管到底读取了多少数据,我采取的办法时只要缓冲区有数据就读取,每次读取的放在一个另外的缓冲区重新组合。你可以GetLastError()看,ReadFile返回的错误多半是ERROR_IO_PENDING. 表示操作还没有完成,有操作系统在自动进行。
      

  2.   

    请注意OVERLAPPED结构的使用,以及怎样实现了非阻塞通信。 UINT CommWatchProc(HWND hSendWnd){   DWORD dwEvtMask=0 ;   SetCommMask( hCom, EV_RXCHAR|EV_TXEMPTY );//有哪些串口事件需要监视?   WaitCommEvent( hCom, &dwEvtMask, os );// 等待串口通信事件的发生   检测返回的dwEvtMask,知道发生了什么串口事件:   if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR){ // 缓冲区中有数据到达   COMSTAT ComStat ; DWORD dwLength;   ClearCommError(hCom, &dwErrorFlags, &ComStat ) ;   dwLength = ComStat.cbInQue ; //输入缓冲区有多少数据?   if (dwLength > 0) { BOOL fReadStat ;     fReadStat = ReadFile( hCom, lpBuffer,dwLength, &dwBytesRead;             &READ_OS( npTTYInfo ) ); //读数据 注:我们在CreareFile()时使用了FILE_FLAG_OVERLAPPED,现在ReadFile()也必须使用   LPOVERLAPPED结构.否则,函数会不正确地报告读操作已完成了.     使用LPOVERLAPPED结构, ReadFile()立即返回,不必等待读操作完成,实现非阻塞     通信.此时, ReadFile()返回FALSE, GetLastError()返回ERROR_IO_PENDING. if (!fReadStat){    if (GetLastError() == ERROR_IO_PENDING){      while(!GetOverlappedResult(hCom,        &READ_OS( npTTYInfo ), & dwBytesRead, TRUE )){        dwError = GetLastError();        if(dwError == ERROR_IO_INCOMPLETE) continue;              //缓冲区数据没有读完,继续        …… ……          ::PostMessage((HWND)hSendWnd,WM_NOTIFYPROCESS,0,0);//通知主线程,串口收到数据  }   所谓的非阻塞通信,也即异步通信。是指在进行需要花费大量时间的数据读写操作(不仅仅是指串行通信操作)时,一旦调用ReadFile()、WriteFile(), 就能立即返回,而让实际的读写操作在后台运行;相反,如使用阻塞通信,则必须在读或写操作全部完成后才能返回。由于操作可能需要任意长的时间才能完成,于是问题就出现了。 非常阻塞操作还允许读、写操作能同时进行(即重叠操作?),在实际工作中非常有用。 要使用非阻塞通信,首先在CreateFile()时必须使用FILE_FLAG_OVERLAPPED;然后在 ReadFile()时lpOverlapped参数一定不能为NULL,接着检查函数调用的返回值,调用GetLastError(),看是否返回ERROR_IO_PENDING。如是,最后调用GetOverlappedResult()返回重叠操作(overlapped operation)的结果;WriteFile()的使用类似。 
      

  3.   

    试试用这个吧 CRITICAL_SECTION (以临界区方式来处理多线程访问冲突)