SerialPort类 问题

tongwei321 2009-09-25 07:00:40
这是SerialPort类监视线程

我们把读写串口的操作全部交给监视线程,现在简单看一下监视线程的大致流程:

检查串口-->进入循环{WaitCommEvent(不阻塞询问)询问事件-->如果有事件来到-->到相应处理(关闭\读\写)}

详细代码如下:

view plaincopy to clipboardprint?
//监视串口函数
UINT CSerialPort::CommThread(LPVOID pParam)
{
// Cast the void pointer passed to the thread back to
// a pointer of CSerialPort class
CSerialPort *port = (CSerialPort*)pParam;

// Set the status variable in the dialog class to
// TRUE to indicate the thread is running.
port->m_bThreadAlive = TRUE;

// Misc. variables
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;

// Clear comm buffers at startup
//检查串口是否打开
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

// begin forever loop. This loop will run as long as the thread is alive.
//不断读取数据
for (;;)
{

// Make a call to WaitCommEvent(). This call will return immediatly
// because our port was created as an async port (FILE_FLAG_OVERLAPPED
// and an m_OverlappedStructerlapped structure specified). This call will cause the
// m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to
// be placed in a non-signeled state if there are no bytes available to be read,
// or to a signeled state if there are bytes available. If this event handle
// is set to the non-signeled state, it will be set to signeled when a
// character arrives at the port.

// we do this for each port!
/********************************************************************
WaitCommEvent函数第3个参数1pOverlapped可以是一个OVERLAPPED结构的变量指针
,也可以是NULL,当用NULL时,表示该函数是同步的,否则表示该函数是异步的。
调用WaitCommEvent时,如果异步操作不能立即完成,会立即返回FALSE,系统在
WaitCommEvent返回前将OVERLAPPED结构成员hEvent设为无信号状态,等到产生通信
事件时,系统将其置有信号
***********************************************************************/
bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);//表示该函数是异步的


if (!bResult)
{
//如果WaitCommEvent返回Error为NULL,则查询错误信息
// If WaitCommEvent() returns FALSE, process the last error to determin
// the reason..
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING: //正常情况,没有字符可读
{
// This is a normal return value if there are no bytes
// to read at the port.
// Do nothing and continue
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: //发生其他错误
{
// All other error codes indicate a serious error has
// occured. Process this error.
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else //WaitCommEvent()能正确返回
{
// If WaitCommEvent() returns TRUE, check to be sure there are
// actually bytes in the buffer to read.
//
// If you are reading more than one byte at a time from the buffer
// (which this program does not do) you will have the situation occur
// where the first byte to arrive will cause the WaitForMultipleObjects()
// function to stop waiting. The WaitForMultipleObjects() function
// resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
// as it returns.
//
// If in the time between the reset of this event and the call to
// ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
// to the signeled state. When the call to ReadFile() occurs, it will
// read all of the bytes from the buffer, and the program will
// loop back around to WaitCommEvent().
//
// At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
// but there are no bytes available to read. If you proceed and call
// ReadFile(), it will return immediatly due to the async port setup, but
// GetOverlappedResults() will not return until the next character arrives.
//
// It is not desirable for the GetOverlappedResults() function to be in
// this state. The thread shutdown event (event 0) and the WriteFile()
// event (Event2) will not work if the thread is blocked by GetOverlappedResults().
//
// The solution to this is to check the buffer with a call to ClearCommError().
// This call will reset the event handle, and if there are no bytes to read
// we can loop back through WaitCommEvent() again, then proceed.
// If there are really bytes to read, do nothing and proceed.

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.
//等待3个事件:关断/读/写,有一个事件发生就返回
Event = WaitForMultipleObjects(3, //3个事件
port->m_hEventArray,//事件数组
FALSE, //有一个事件发生就返回
INFINITE); //超时时间

switch (Event)
{
case 0:
{
// Shutdown event. This is event zero so it will be
// the higest priority and be serviced first.
//关断事件,关闭串口
CloseHandle(port->m_hComm);
port->m_hComm=NULL;
port->m_bThreadAlive = FALSE;

// Kill this thread. break is not needed, but makes me feel better.
AfxEndThread(100);

break;
}
case 1: // read event 将定义的各种消息发送出去
{
//接收
GetCommMask(port->m_hComm, &CommEvent);
if (CommEvent & EV_RXCHAR)
// Receive character event from port.
ReceiveChar(port, comstat);
if (CommEvent & EV_CTS)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_BREAK)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_ERR)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RING)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);

if (CommEvent & EV_RXFLAG)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);

break;
}
case 2: // write event发送数据
{
// Write character event from port
//写
WriteChar(port);
break;
}

} // end switch

} // close forever loop

return 0;
}
这里有数据到来了就会触发读事件m_ov.hEvent,使其为有信号状态,在读完数据后m_ov.hEvent是不是变成了无信号状态,这是怎么实现的?我找不到ResetEvent(m_ov.hEvent)这个函数,请教一下 谢谢啊
...全文
97 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
mfr007 2009-09-30
  • 打赏
  • 举报
回复
我也用过这个串口类
回家看看源程序,给你解释下,现在忘记了

可以一起讨论
邮箱 mfr007@126.com

15,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧