WaitCommEvent等待EV_RXCHAR事件为什么会发生2次?

zhangjingrui   2009-11-12 14:32 楼主
writefile()指令之后,为什么会收到两次EV_RXCHAR事件?按道理应该收到一次EV_RXCHAR事件,可是收到两次EV_RXCHAR事件
这到底是什么原因???

  1. ...
  2. for(;;)
  3.     {
  4.         bResult=WaitCommEvent(m_hCom,&hMask,&ReadOver);   
  5.         if(OpenCloseFlag==1)  //串口已被打开才做下一部
  6.         {
  7.             if(!bResult)
  8.             {
  9.                 switch(dwErr=GetLastError())
  10.                 {
  11.                     case ERROR_IO_PENDING:
  12.                          Flag^=1;
  13.                          break;
  14.                    /*case 87:
  15.                         break;*/
  16.                     default:
  17.                         SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"WaitCommEvent Error");
  18.                         goto ErrorNext;
  19.                 }
  20.             }else
  21.             {
  22.                 bResult=ClearCommError(m_hCom,&dwErr,&comstat);
  23.                 if(comstat.cbInQue==0)
  24.                    continue;
  25.             }         
  26.             WaitForSingleObject(ReadOver.hEvent,INFINITE);///等侍异步操作完成
  27.             Flag=0;
  28.             GetCommMask(m_hCom,&hMask);
  29.             if(hMask & EV_RXCHAR)         
  30.             {   
  31.                 EnterCriticalSection(§ion);
  32.                    bResult=ClearCommError(m_hCom,&dwErr,&comstat);
  33.                 if(!ReadFile(m_hCom,pszRecv,100,&ReadBytes,&ReadOver))
  34.                 {
  35.                     switch(dwErr=GetLastError())
  36.                     {
  37.                         case ERROR_IO_PENDING:
  38.                             Flag^=1;
  39.                             break;
  40.                         default:
  41.                             goto ErrorNext;
  42.                     }
  43.                 }
  44.                      
  45.                 if(Flag & 1)
  46.                 {
  47.                      SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"正在读取数据");
  48.                      WaitForSingleObject(ReadOver.hEvent,INFINITE);

  49.                     if(GetOverlappedResult(m_hCom,&ReadOver,&ReadBytes,TRUE))
  50.                     {
  51.                         SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"读取数据完成");
  52.                         SetDlgItemText((HWND)lparam,IDC_SHOWINFO,pszRecv);
  53.                     }
  54.                 }   
  55.                  
  56.                         
  57.                LeaveCriticalSection(§ion);

  58.             }
  59. ErrorNext:
  60.         Flag=0;
  61.         PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
  62.   
  63.         }   
  64.      
  65.     }
  66.     return 1;
  67. }
  68. ...





回复评论 (4)

先调用SetCommMask函数设定要等待的串口事件,例如串口有数据到来(EV_RXCHAR)事件;然后在读串口线程中调用WaitCommEvent阻塞线程,等待EV_RXCHAR事件的发生。当等待的EV_RXCHAR事件发生时,调用ClearCommError函数清除通信错误信息,并且获取串口的当前状态,主要是获取串口接收缓冲区中的字节数,然后调用ReadFile函数将接收缓冲区的数据全部读出。最后调用PostMessage函数将这些数据发送给主线程进行处理。
点赞  2009-11-13 08:11
引用: 引用 1 楼 duojinian 的回复:
先调用SetCommMask函数设定要等待的串口事件,例如串口有数据到来(EV_RXCHAR)事件;然后在读串口线程中调用WaitCommEvent阻塞线程,等待EV_RXCHAR事件的发生。当等待的EV_RXCHAR事件发生时,调用ClearCommError函数清除通信错误信息,并且获取串口的当前状态,主要是获取串口接收缓冲区中的字节数,然后调用ReadFile函数将接收缓冲区的数据全部读出。最后调用PostMessage函数将这些数据发送给主线程进行处理。

你好,谢谢你的回答!按照你的手法好像不行!贴上读线程代码:

  1. DWORD WINAPI ReadCommThread(LPARAM lparam)///读线程
  2. {

  3.     extern HANDLE m_hCom;
  4.     extern OpenCloseFlag;
  5.     extern unsigned char pszRecv[1024];
  6.     DWORD ReadBytes;
  7.         DWORD bResult;
  8.         DWORD dwErr;
  9.         OVERLAPPED ReadOver={0};
  10.         DWORD hMask;
  11.         DWORD CommEvent;
  12.         int i=0;
  13.         CRITICAL_SECTION section;
  14.         COMSTAT comstat;

  15.         DWORD Flag=0;
  16.         memset(&ReadOver,0x00,sizeof(OVERLAPPED));
  17.         ReadOver.Internal=0;
  18.         ReadOver.InternalHigh=0;
  19.        ReadOver.Offset=0;
  20.        ReadOver.OffsetHigh=0;
  21.         ReadOver.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  22.         PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
  23.         InitializeCriticalSection(§ion);
  24.   for(;;)
  25.     {
  26.    
  27.         bResult=WaitCommEvent(m_hCom,&hMask,&ReadOver);   

  28.         if(OpenCloseFlag==1)  //串口已被打开才做下一部
  29.         {
  30.             if(!bResult)
  31.             {
  32.                 switch(dwErr=GetLastError())
  33.                 {
  34.                     case ERROR_IO_PENDING:
  35.                          Flag^=1;
  36.                          break;
  37.                    /*case 87:
  38.                         break;*/
  39.                     default:
  40.                         SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"WaitCommEvent Error");
  41.                         goto ErrorNext;
  42.                 }
  43.             }else
  44.             {
  45.                 bResult=ClearCommError(m_hCom,&dwErr,&comstat);
  46.                 if(comstat.cbInQue==0)
  47.                    continue;
  48.             }         
  49.             WaitForSingleObject(ReadOver.hEvent,INFINITE);///等侍异步操作完成
  50.             Flag=0;
  51.             GetCommMask(m_hCom,&hMask);
  52.             if(hMask & EV_RXCHAR)         
  53.             {   
  54.                 EnterCriticalSection(§ion);
  55.                    bResult=ClearCommError(m_hCom,&dwErr,&comstat);
  56.                 if(!ReadFile(m_hCom,pszRecv,100,&ReadBytes,&ReadOver))
  57.                 {
  58.                     switch(dwErr=GetLastError())
  59.                     {
  60.                         case ERROR_IO_PENDING:
  61.                             Flag^=1;
  62.                             break;
  63.                         default:
  64.                             goto ErrorNext;
  65.                     }
  66.                 }
  67.                      
  68.                 if(Flag & 1)
  69.                 {
  70.                      SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"正在读取数据");
  71.                      WaitForSingleObject(ReadOver.hEvent,INFINITE);

  72.                     if(GetOverlappedResult(m_hCom,&ReadOver,&ReadBytes,TRUE))
  73.                     {
  74.                         SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"读取数据完成");
  75.                         SetDlgItemText((HWND)lparam,IDC_SHOWINFO,pszRecv);
  76.                     }
  77.                 }   
  78.                  
  79.                         
  80.                LeaveCriticalSection(§ion);

  81.             }
  82. ErrorNext:
  83.         Flag=0;
  84.         PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
  85.   
  86.         }   
  87.      
  88.     }
  89.     return 1;
  90. }




点赞  2009-11-13 08:40
这是写入串口的函数:

  1. BOOL WriteComm(HWND hWnd)   //写串口
  2. {
  3.     extern char *pszReadWriteComm;
  4.     extern HANDLE m_hCom;
  5.     extern FileSize,WriteFlag;
  6.     char pszWriteBuffer[1024];
  7.         DWORD WriteBytes;
  8.         OVERLAPPED hWriteOver;///重叠IO
  9.         int FlagState=1,dwErr;
  10.     // OVERLAPPED结构实始化为0
  11.         memset(&hWriteOver,0x00,sizeof(OVERLAPPED));
  12.         hWriteOver.Internal=0;
  13.         hWriteOver.InternalHigh=0;
  14.         hWriteOver.Offset=0;
  15.         hWriteOver.OffsetHigh=0;
  16.         hWriteOver.hEvent=CreateEvent(0,TRUE,FALSE,0);
  17.     if(hWriteOver.hEvent!=NULL)
  18.         {
  19.                 if(WriteFlag==1)
  20.                 {
  21.                         if(!WriteFile(m_hCom,pszReadWriteComm,FileSize,&WriteBytes,&hWriteOver))
  22.                         {
  23.                                 if(GetLastError()!=ERROR_IO_PENDING)
  24.                                         MessageBox(hWnd,"写串口失败",0,MB_OK);
  25.                                 else
  26.                                 {
  27.                     
  28.                                         dwErr=WaitForSingleObject(hWriteOver.hEvent,INFINITE);
  29.                                         switch(dwErr)
  30.                                         {
  31.                         
  32.                                             case WAIT_OBJECT_0:
  33.                                                     if(!GetOverlappedResult(m_hCom,&hWriteOver,&WriteBytes,FALSE))
  34.                                                             MessageBox(hWnd,"重叠IO失败",0,MB_OK);
  35.                                            
  36.                                                     break;
  37.                                             default:
  38.                                                     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
  39.                                                     break;
  40.                                         }

  41.                                  }
  42.                          }
  43.             }
  44.                 else
  45.                 {

  46.                     byte buffsg[8]={0x00,0x03,0x00,0x50,0x00,0x0A,0x00,0x00};
  47.                 if(!WriteFile(m_hCom,buffsg,8,&WriteBytes,&hWriteOver))
  48.                         {
  49.                    //ShowError();
  50.                                 if(GetLastError()!=ERROR_IO_PENDING)
  51.                                         MessageBox(hWnd,"写串口失败",0,MB_OK);
  52.                                 else
  53.                                 {
  54.          
  55.                                         dwErr=WaitForSingleObject(hWriteOver.hEvent,INFINITE);
  56.                                         switch(dwErr)
  57.                                         {
  58.                                             case WAIT_OBJECT_0:
  59.                                                     if(!GetOverlappedResult(m_hCom,&hWriteOver,&WriteBytes,FALSE))
  60.                                                             MessageBox(hWnd,"重叠IO失败",0,MB_OK);
  61.                                                     break;
  62.                                             default:
  63.                                                     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
  64.                                                     break;

  65.                                         }

  66.                                 }
  67.                         }

  68.                 }

  69.         }

  70.      PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);
  71.        
  72.         return TRUE;
  73. }

点赞  2009-11-13 08:42
我给串口发送指令后,仪表也返回串口数据。问题是现在EV_RXCHAR被触发了两次,第二次触发好像是没用,为什么会触发第二次,实在是找不到原因???
点赞  2009-11-13 08:45
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复