这到底是什么原因???
...
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(§ion);
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(§ion);
}
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
你好,谢谢你的回答!按照你的手法好像不行!贴上读线程代码:
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(§ion);
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(§ion);
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(§ion);
}
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
你好,谢谢你的回答!按照你的手法好像不行!贴上读线程代码:
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(§ion);
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(§ion);
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(§ion);
}
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被触发了两次,第二次触发好像是没用,为什么会触发第二次,实在是找不到原因???