串口通信模块5:串口操作自定义类(2)

来源:互联网 发布:公共安全与大数据 编辑:程序博客网 时间:2024/06/07 21:04

1.ProcessErrorMessage()函数的实现:

ProcessErrorMessage()函数负责处理并提示错误信息,其实现过程如下:
void CMySerial::ProcessErrorMessage(char* ErrorText){char* Temp = new char[200];LPVOID lpMsgBuf;    //保存错误信息的指针//将GetLastError()得到的错误信息转化成字符串信息FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf,0,NULL);sprintf(Temp, "WARNING: %s Failed with the following error:\n %s \nPort: %d\n",(char*)ErrorText,lpMsgBuf,m_nPortNr);   //整合完整的错误信息MessageBox(NULL, (LPCWSTR)Temp, (LPTSTR)"Application Error", MB_ICONSTOP);  //提示错误信息LocalFree(lpMsgBuf);      //释放资源delete[] Temp;}
设计思想:
首先,调用FormatMessage()函数,将GetLastError()函数返回的错误号转化成字符串信息。然后,将刚刚转化的字符串信息与错误发生的位置,整合成一个完整的错误信息字符串,并保存到Temp指向的空间中。最后,调用MessageBox()函数,将整合后的信息以消息框的形式弹出给用户。
FormatMessage()函数原型如下:
/*DWORD FormatMessageA(DWORD dwFlags,           //错误信息类型标志LPCVOID lpSource,        //指定本地信息定义,其依赖于第一个参数的设置DWORD dwMessageId,       //指定被请求消息标识DWORD dwLanguageId,      //指定被请求的消息语言标示LPSTR lpBuffer,          //指向一个格式化的消息缓冲区DWORD nSize,             //指定输出缓冲区的大小va_list *Arguments       //指向在格式化消息中被用来插入数值的一个32位数值的数组);*/

2.串口线程函数的实现

串口线程处理函数CommThread()实现监控差UN扣时间爱你的功能,根据串口事件进行相应的实现,实现如下:
UINT CMySerial::CommTread(LPVOID pParam){CMySerial* port = (CMySerial*)pParam;  //串口类型的指针//串口线程活动标识port->m_bThreadAlive = TRUE;//串口信息变量DWORD BytesTransferred = 0;DWORD Event = 0;DWORD COommEvent = 0;DWORD dwError = 0;COMSTAT comstat;//强制关闭串口if (port->m_hComm){//清空串口缓存PurgeComm(port->m_hComm, PURGE_RXABORT | PURGE_TXABORT       | PURGE_RXCLEAR | PURGE_TXCLEAR);}//线程的循环体for (;;){BOOL bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);if (!bResult){//读取失败处理switch ( dwError = GetLastError() ){case ERROR_IO_PENDING: break; //读取串口为空case 87: break;default: //错误处理{port->ProcessErrorMessage("WaitCommEvent()");break;}}}else{//清空串口错误BOOL bResult = ClearCommError(port->m_hComm, &dwError, &comstat);if (comstat.cbInQue == 0)continue;}//获取串口事件并进行相应处理Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);switch (Event){case 0: //关闭串口CloseHandle(port->m_hComm);port->m_hComm = NULL;port->m_bThreadAlive = FALSE;AfxEndThread(100);break;case 1: //读串口GetCommMask( port->m_hComm, &CommEvent );if (CommEvent & EV_RXCHAR)ReceiveChar(port, comstat);break;case 2: //写串口WriteChar(port);break;}}return 0;}
设计思想:
1.获取保存串口类的指针;并将串口线程活动标识设置为真。
2.判断串口是否已经打开?如果是,那么清空串口缓冲。
3.设计串口线程主循环体:首先,等待串口的异步通信事件,如果等待失败调用相应处理函数;否则获取串口中尚未读取的字节数。然后,我们需要对获取的字节数进行判断是否为空?如果为空,跳出本次循环;最后,等待串口的3个事件,并判断接收到的串口事件类型。包括:关闭串口事件;处理读串口事件;处理写串口事件。
这里需要强调WaitCommEvent()函数,该函数是指为一个特指的通信设备等待一个事件发生,该函数所监控的事件是与该设备句柄相关联的一系列事件

/*BOOL WINAPI WaitCommEvent(HANDLE       hFile,       //指向通信设备的一个句柄LPDWORD      lpEvtMask,   //一个指向DWORD的指针LPOVERLAPPED lpOverlapped //指向OVERLAPPED结构体的指针);*/
参数lpOverlapped是指向OVERLAPPED结构体的一个指针。如果hFile采用异步方式打开,在CreateFile()函数中,该参数设置为FILE_FLAG_OVERLAPPED。该参数不能指向一个空的OVERLAPPED结构体。如果hfile是采用异步方式打开的,而lpOverlapped指向了一个空的结构体,那么函数就会发出错误报告,等到的操作已经完成(而此时等待的操作可能还没有完成)。

3.串口进程监控函数的实现

这里采用函数StartMonitoring()、函数RestartMonitoring()、函数StopMonitoring()分别监控串口进程的开始、重启和挂起。
//启动串口线程BOOL CMySerial::StartMonitoring(){if (!(m_Thread = AfxBeginThread(CommTread, this)))return FALSE;TRACE(" Thread started\n ");return TRUE;}//重启串口进程BOOL CMySerial::RestarMonitoring(){TRACE(" Thread resumed\n ");m_Thread->ResumeThread();return TRUE;}//挂起串口线程BOOL CMySerial::StopMonitoring(){TRACE(" Thread suspended\n ");m_Thread->SuspendThread();return TRUE;}
设计思想:

这3个函数实现起来是非常轻松的,分别调用了AfxBginThread()、ResumeThread()和SuspendThread()函数来实现串口进程的开启、重启以及挂起功能。

4.串口关闭函数的实现

关闭串口函数直接调用SetEvent()函数就可以实现,具体是设置关闭串口事件的状态为标记。
//串口关闭void CMySerial::ClosePort(){SetEvent(m_hShutdownEvent);}
0 0
原创粉丝点击