串口通信模块5:串口操作自定义类(2)
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); }
串口通信模块5:串口操作自定义类(2)相关推荐
- 串口通信模块4:串口操作自定义类(1)
为了以后使用方便,将串口的属性及操作封装成一个类.对串口的操作可以直接通过调用这个串口类提供的几个函数接口即可. 1.CMySerial类的定义:MySerial.h #pragma once #in ...
- 2、Collections操作(自定义类)的各种实现
2019独角兽企业重金招聘Python工程师标准>>> 1.排序(sort) 要想实现排序,必须实现compare方法,这样Collection才知道是怎样的排序规则.普通的数据类型 ...
- 串口通信模块5:串口操作自定义类(3)
在上述代码基础之上,本页主要讨论串口数据的接受.发送以及与窗口类函数的通信. 1.读取串口数据函数的实现 //接收串口数据 void CMySerial::ReceiveChar(CMySerial* ...
- java中自定义日期类_java日期操作自定义类
每次当需要对日期进行处理的时候,总是会记不住库.方法和格式,所以就自己简单封装了下:包含了大部分功能,部分不常用的没有实现. package com.tunicorn.marketing.utils; ...
- serialport接收串口数据_C#串口操作类,包括串口读写操作
串口进行操作的类,其中包括写和读操作,类可设置串口参数.设置接收函数.打开串口资源.关闭串口资源,操作完成后,一定要关闭串口.接收串口数据事件.接收数据出错事件.获取当前全部串口.把字节型转换成十六进 ...
- 串口通信模块3:串口通信编程基础(读写、关闭)
上一节总结了如何打开串口并讨论了如何配置串口,本节是在上一节的基础上,进一步讨论串口编程的基础--如何进行文件读写?如何关闭串口? 1. 读写串口 串口的读写操作和文件的读写操作是一样的,也是通过Re ...
- (转载)uCOS-II的嵌入式串口通信模块设计
在嵌入式应用中,使用RTOS的主要原因是为了提高系统的可靠性,其次是提高开发效率.缩短开发周期.uCOS-II是一个占先式实时多任务内核,使用对象是嵌入式系统,对源代码适当裁减,很容易移植到8~32位 ...
- arduino封装了一个无线串口模块LC12S的操作库
前一段时间接触到一个比较好用的2.4G无线串口通信模块LC12S, 在淘宝上仅四五块钱,收发一体,比较好用. 我照着技术文档封装了这个设置操作的库 demo代码: #include <Ardui ...
- 串口通信模块2:串口通信编程基础(打开、配置)
有两种方式可以操作串口:同步操作方式和异步操作方式(即重叠操作方式).同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程):而异步操作方式 ...
最新文章
- JS,Jquery获取各种屏幕的宽度和高度
- SpringCloud SpringBoot 推荐
- 发那科机器人网段_FANUC机器人基本操作指导
- aix Oracle 限制访问,改变AIX上使用oracle的一些限制
- 佳能102种相片风格_一位妈妈用蔬菜水果等,为女儿拍了一组相片,没想到在INS火了...
- 使用 matlab 数字图像处理(五)—— 双线性插值(Bilinear Interpolation)
- android inflater 用法
- java运算符的优先级别
- 【全栈编程系列】SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题、配置启动异常No SecurityManager...)
- 可见光通信在室内定位及IoT上的应用展示
- android脚本模拟器,android运行模拟器脚本(批处理)
- 每日一题---摔手机
- JAVA计算机毕业设计中华二十四节气文化传承宣展平台Mybatis+源码+数据库+lw文档+系统+调试部署
- Axure下拉框的多选与取消
- HBase数据库原理介绍
- 视频去除水印,只需两分钟随时学会
- 为什么找不到AppData、Default、ProgramData文件
- 边缘计算初探:什么是边缘计算,它能做什么?
- 读《Effective java 中文版》(2)
- 未能加载或程序集“XXXX,Version=0.0.0.0,Culter=neutral,PublicKeyToken=null”或它的某一个依赖项。试图加载格式不正确的程序。...