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

时间:2022-08-19 08:05:18
writefile()指令之后,为什么会收到两次EV_RXCHAR事件?按道理应该收到一次EV_RXCHAR事件,可是收到两次EV_RXCHAR事件
这到底是什么原因??? 

 ...
 for(;;)
    {
        bResult=WaitCommEvent(m_hCom,&hMask,&ReadOver);    
        if(OpenCloseFlag==1)  //串口已被打开才做下一部
        { 
            if(!bResult)
            {
                switch(dwErr=GetLastError())
                {
                    case ERROR_IO_PENDING:
                         Flag^=1;
                         break;
                   /*case 87:
                        break;*/
                    default:
                        SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"WaitCommEvent Error");
                        goto ErrorNext;
                }
            }else
            {
                bResult=ClearCommError(m_hCom,&dwErr,&comstat);
                if(comstat.cbInQue==0)
                   continue;
            }          
            WaitForSingleObject(ReadOver.hEvent,INFINITE);///等侍异步操作完成
            Flag=0;
            GetCommMask(m_hCom,&hMask);
            if(hMask & EV_RXCHAR)          
            {    
                EnterCriticalSection(&section);
                   bResult=ClearCommError(m_hCom,&dwErr,&comstat);
                if(!ReadFile(m_hCom,pszRecv,100,&ReadBytes,&ReadOver)) 
                {
                    switch(dwErr=GetLastError())
                    {
                        case ERROR_IO_PENDING:
                            Flag^=1;
                            break;
                        default:
                            goto ErrorNext;
                    }
                } 
                      
                if(Flag & 1)
                {
                     SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"正在读取数据");
                     WaitForSingleObject(ReadOver.hEvent,INFINITE);
 
                    if(GetOverlappedResult(m_hCom,&ReadOver,&ReadBytes,TRUE))
                    {
                        SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"读取数据完成");
                        SetDlgItemText((HWND)lparam,IDC_SHOWINFO,pszRecv);
                    }
                }    
                 
                         
               LeaveCriticalSection(&section);
 
            }
ErrorNext:
        Flag=0; 
        PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
  
        }    
     
    }
    return 1;
}
...





4 个解决方案

#1


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

#2


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

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

 DWORD WINAPI ReadCommThread(LPARAM lparam)///读线程
{
 
    extern HANDLE m_hCom;
    extern OpenCloseFlag;
    extern unsigned char pszRecv[1024];
    DWORD ReadBytes;
DWORD bResult;
DWORD dwErr;
OVERLAPPED ReadOver={0};
DWORD hMask;
DWORD CommEvent;
int i=0;
CRITICAL_SECTION section;
COMSTAT comstat;
 
DWORD Flag=0;
memset(&ReadOver,0x00,sizeof(OVERLAPPED));
ReadOver.Internal=0;
ReadOver.InternalHigh=0;
       ReadOver.Offset=0;
       ReadOver.OffsetHigh=0;
ReadOver.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); 
InitializeCriticalSection(&section);
  for(;;)
    {
    
        bResult=WaitCommEvent(m_hCom,&hMask,&ReadOver);   
 
        if(OpenCloseFlag==1)  //串口已被打开才做下一部
        { 
            if(!bResult)
            {
                switch(dwErr=GetLastError())
                {
                    case ERROR_IO_PENDING:
                         Flag^=1;
                         break;
                   /*case 87:
                        break;*/
                    default:
                        SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"WaitCommEvent Error");
                        goto ErrorNext;
                }
            }else
            {
                bResult=ClearCommError(m_hCom,&dwErr,&comstat);
                if(comstat.cbInQue==0)
                   continue;
            }          
            WaitForSingleObject(ReadOver.hEvent,INFINITE);///等侍异步操作完成
            Flag=0;
            GetCommMask(m_hCom,&hMask);
            if(hMask & EV_RXCHAR)          
            {    
                EnterCriticalSection(&section);
                   bResult=ClearCommError(m_hCom,&dwErr,&comstat);
                if(!ReadFile(m_hCom,pszRecv,100,&ReadBytes,&ReadOver)) 
                {
                    switch(dwErr=GetLastError())
                    {
                        case ERROR_IO_PENDING:
                            Flag^=1;
                            break;
                        default:
                            goto ErrorNext;
                    }
                } 
                      
                if(Flag & 1)
                {
                     SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"正在读取数据");
                     WaitForSingleObject(ReadOver.hEvent,INFINITE);
 
                    if(GetOverlappedResult(m_hCom,&ReadOver,&ReadBytes,TRUE))
                    {
                        SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"读取数据完成");
                        SetDlgItemText((HWND)lparam,IDC_SHOWINFO,pszRecv);
                    }
                }    
                 
                         
               LeaveCriticalSection(&section);
 
            }
ErrorNext:
        Flag=0; 
        PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
  
        }    
     
    }
    return 1;
}
 



#3


这是写入串口的函数:

BOOL WriteComm(HWND hWnd)   //写串口
{
    extern char *pszReadWriteComm;
    extern HANDLE m_hCom;
    extern FileSize,WriteFlag;
    char pszWriteBuffer[1024];
DWORD WriteBytes;
OVERLAPPED hWriteOver;///重叠IO
int FlagState=1,dwErr;
    // OVERLAPPED结构实始化为0
memset(&hWriteOver,0x00,sizeof(OVERLAPPED));
hWriteOver.Internal=0;
hWriteOver.InternalHigh=0;
hWriteOver.Offset=0;
hWriteOver.OffsetHigh=0;
hWriteOver.hEvent=CreateEvent(0,TRUE,FALSE,0);
    if(hWriteOver.hEvent!=NULL)
{
if(WriteFlag==1)
{
if(!WriteFile(m_hCom,pszReadWriteComm,FileSize,&WriteBytes,&hWriteOver))
{
if(GetLastError()!=ERROR_IO_PENDING)
MessageBox(hWnd,"写串口失败",0,MB_OK);
else
{
                    
dwErr=WaitForSingleObject(hWriteOver.hEvent,INFINITE);
switch(dwErr)
{
                        
     case WAIT_OBJECT_0:
     if(!GetOverlappedResult(m_hCom,&hWriteOver,&WriteBytes,FALSE))
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
    
     break;
     default:
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
     break;
}

 }
 }
    }
else
{
 
    byte buffsg[8]={0x00,0x03,0x00,0x50,0x00,0x0A,0x00,0x00};
         if(!WriteFile(m_hCom,buffsg,8,&WriteBytes,&hWriteOver))
{
                   //ShowError();
if(GetLastError()!=ERROR_IO_PENDING)
MessageBox(hWnd,"写串口失败",0,MB_OK);
else
{
         
dwErr=WaitForSingleObject(hWriteOver.hEvent,INFINITE);
switch(dwErr)
{
     case WAIT_OBJECT_0:
     if(!GetOverlappedResult(m_hCom,&hWriteOver,&WriteBytes,FALSE))
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
     break;
     default:
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
     break;

}

}
}

}

}

     PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);

return TRUE;
}

#4


我给串口发送指令后,仪表也返回串口数据。问题是现在EV_RXCHAR被触发了两次,第二次触发好像是没用,为什么会触发第二次,实在是找不到原因???

#1


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

#2


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

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

 DWORD WINAPI ReadCommThread(LPARAM lparam)///读线程
{
 
    extern HANDLE m_hCom;
    extern OpenCloseFlag;
    extern unsigned char pszRecv[1024];
    DWORD ReadBytes;
DWORD bResult;
DWORD dwErr;
OVERLAPPED ReadOver={0};
DWORD hMask;
DWORD CommEvent;
int i=0;
CRITICAL_SECTION section;
COMSTAT comstat;
 
DWORD Flag=0;
memset(&ReadOver,0x00,sizeof(OVERLAPPED));
ReadOver.Internal=0;
ReadOver.InternalHigh=0;
       ReadOver.Offset=0;
       ReadOver.OffsetHigh=0;
ReadOver.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); 
InitializeCriticalSection(&section);
  for(;;)
    {
    
        bResult=WaitCommEvent(m_hCom,&hMask,&ReadOver);   
 
        if(OpenCloseFlag==1)  //串口已被打开才做下一部
        { 
            if(!bResult)
            {
                switch(dwErr=GetLastError())
                {
                    case ERROR_IO_PENDING:
                         Flag^=1;
                         break;
                   /*case 87:
                        break;*/
                    default:
                        SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"WaitCommEvent Error");
                        goto ErrorNext;
                }
            }else
            {
                bResult=ClearCommError(m_hCom,&dwErr,&comstat);
                if(comstat.cbInQue==0)
                   continue;
            }          
            WaitForSingleObject(ReadOver.hEvent,INFINITE);///等侍异步操作完成
            Flag=0;
            GetCommMask(m_hCom,&hMask);
            if(hMask & EV_RXCHAR)          
            {    
                EnterCriticalSection(&section);
                   bResult=ClearCommError(m_hCom,&dwErr,&comstat);
                if(!ReadFile(m_hCom,pszRecv,100,&ReadBytes,&ReadOver)) 
                {
                    switch(dwErr=GetLastError())
                    {
                        case ERROR_IO_PENDING:
                            Flag^=1;
                            break;
                        default:
                            goto ErrorNext;
                    }
                } 
                      
                if(Flag & 1)
                {
                     SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"正在读取数据");
                     WaitForSingleObject(ReadOver.hEvent,INFINITE);
 
                    if(GetOverlappedResult(m_hCom,&ReadOver,&ReadBytes,TRUE))
                    {
                        SetDlgItemText((HWND)lparam,IDC_COMMSTATE,"读取数据完成");
                        SetDlgItemText((HWND)lparam,IDC_SHOWINFO,pszRecv);
                    }
                }    
                 
                         
               LeaveCriticalSection(&section);
 
            }
ErrorNext:
        Flag=0; 
        PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
  
        }    
     
    }
    return 1;
}
 



#3


这是写入串口的函数:

BOOL WriteComm(HWND hWnd)   //写串口
{
    extern char *pszReadWriteComm;
    extern HANDLE m_hCom;
    extern FileSize,WriteFlag;
    char pszWriteBuffer[1024];
DWORD WriteBytes;
OVERLAPPED hWriteOver;///重叠IO
int FlagState=1,dwErr;
    // OVERLAPPED结构实始化为0
memset(&hWriteOver,0x00,sizeof(OVERLAPPED));
hWriteOver.Internal=0;
hWriteOver.InternalHigh=0;
hWriteOver.Offset=0;
hWriteOver.OffsetHigh=0;
hWriteOver.hEvent=CreateEvent(0,TRUE,FALSE,0);
    if(hWriteOver.hEvent!=NULL)
{
if(WriteFlag==1)
{
if(!WriteFile(m_hCom,pszReadWriteComm,FileSize,&WriteBytes,&hWriteOver))
{
if(GetLastError()!=ERROR_IO_PENDING)
MessageBox(hWnd,"写串口失败",0,MB_OK);
else
{
                    
dwErr=WaitForSingleObject(hWriteOver.hEvent,INFINITE);
switch(dwErr)
{
                        
     case WAIT_OBJECT_0:
     if(!GetOverlappedResult(m_hCom,&hWriteOver,&WriteBytes,FALSE))
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
    
     break;
     default:
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
     break;
}

 }
 }
    }
else
{
 
    byte buffsg[8]={0x00,0x03,0x00,0x50,0x00,0x0A,0x00,0x00};
         if(!WriteFile(m_hCom,buffsg,8,&WriteBytes,&hWriteOver))
{
                   //ShowError();
if(GetLastError()!=ERROR_IO_PENDING)
MessageBox(hWnd,"写串口失败",0,MB_OK);
else
{
         
dwErr=WaitForSingleObject(hWriteOver.hEvent,INFINITE);
switch(dwErr)
{
     case WAIT_OBJECT_0:
     if(!GetOverlappedResult(m_hCom,&hWriteOver,&WriteBytes,FALSE))
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
     break;
     default:
     MessageBox(hWnd,"重叠IO失败",0,MB_OK);
     break;

}

}
}

}

}

     PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);

return TRUE;
}

#4


我给串口发送指令后,仪表也返回串口数据。问题是现在EV_RXCHAR被触发了两次,第二次触发好像是没用,为什么会触发第二次,实在是找不到原因???