串口通信模块4:串口操作自定义类(1)
2016-10-02 18:04
351 查看
为了以后使用方便,将串口的属性及操作封装成一个类。对串口的操作可以直接通过调用这个串口类提供的几个函数接口即可。
在这个类中,事件数组m_hEventArray中的每个数组元素都对应着一个事件。这个数组共有三个元素:一个是写事件,一个是收事件,还有一个是串口关闭事件。
打开串口代码设计的核心思想为:
1.判断串口监控线程是否处于激活状态?如果是,那么需要将它关闭;
2.创建并启动串口的3个事件;
3.创建的事件句柄保存到事件数组里;
4.初始化临界资源;并申请一段数据发送缓存区;
5.保存传入的参数,并锁定临界资源;
6.验证串口是否已关闭?如果没有关闭,则要关闭;
7.打开串口,并判断是否打开串口成功?否则需要我们释放资源后返回;
8.设置串口通信的超时参数。
9.将前面准备好的串口的所有属性设置到串口上,设置失败后需要调用消息盒子进行失败处理。
10.释放资源,清空缓存区,并解锁临界资源,使得其它进程以后可以使用这个临界资源。
1.CMySerial类的定义:MySerial.h
#pragma once #include <Windows.h> #include <afxwin.h> class CMySerial { public: CMySerial(); virtual ~CMySerial(); public: bool OpenSerial(CWnd* pParent, UINT portnr, UINT baud, CHAR parity, UINT databits, UINT stopbits, DWORD dwCommEvents, UINT writebuffersize); //Open the Serial void ClosePort(); // the control function of monitoring thread BOOL StartMonitoring(); BOOL RestarMonitoring(); BOOL StopMonitoring(); DWORD GetWriteBufferSize(); DWORD GetCommEvents(); DCB GetDCB(); // Attain & Save the Data that will transfor and trigle the transfor event. void WriteToPort(char* string); void WriteToPort(char* string, int n); void WriteToPort(LPCSTR string); void WriteToPort(LPCSTR string, int n); protected: void ProcessErrorMessage(char* ErrorText); //deal error event static UINT CommTread(LPVOID pParam); // function to deal serial thread static void ReceiveChar(CMySerial* port, //read serial data COMSTAT comstat); static void WriteChar(CMySerial* port); //write data to serial public: HANDLE m_hComm; //handle to operate serial int m_nWriteSize; //send data protected: CWinThread* m_Thread; // a pointer to thread CRITICAL_SECTION m_csCommunicationSync; // critial临界 resourse BOOL m_bThreadAlive; // the alive state of serial //serial event HANDLE m_hWriteEvent; //write event HANDLE m_hShutdownEvent; //shut down event HANDLE m_hEventArray[3]; //event array DWORD m_dwCommEvents; //mask code of serial event OVERLAPPED m_ov; //set asynchonous I/O operation COMMTIMEOUTS m_CommTimeouts; //structure of serial overtime DCB m_dcb; //DCB structure in serial communication CWnd* m_pParent; //include window pointer of serial operation UINT m_nPortNr; //port number char* m_szWriteBuffer; //area of writedata buffer DWORD m_nWriteBufferSize; //size of writedata buffer };
在这个类中,事件数组m_hEventArray中的每个数组元素都对应着一个事件。这个数组共有三个元素:一个是写事件,一个是收事件,还有一个是串口关闭事件。
2.CMySerial类的实现及代码解析:CMySerial.c
构造及解析函数的实现:CMySerial::CMySerial() { m_hComm = NULL; //初始化串口句柄 //初始化异步操作成员变量 m_ov.Offset = 0; m_ov.OffsetHigh = 0; //创建异步操作的事件成员变量 m_ov.hEvent = NULL; //初始化发送及关闭事件 m_hWriteEvent = NULL; m_hShutdownEvent = NULL; //初始化发送变量 m_szWriteBuffer = NULL; m_nWriteBufferSize = 1; m_bThreadAlive = FALSE; //串口监控线程处于非激活状态 } CMySerial::~CMySerial() { do { SetEvent(m_hShutdownEvent); } while ( m_bThreadAlive ); //监控线程处于激活状态时,关闭串口 if (m_hComm != NULL) { CloseHandle(m_hComm); m_hComm = NULL; //如果上面串口关闭不成功,继续关闭窗口 } if (m_hShutdownEvent != NULL) CloseHandle( m_hShutdownEvent ); //关闭串口并关闭事件句柄 if (m_ov.hEvent != NULL) CloseHandle( m_ov.hEvent ); //关闭串口异步操作事件句柄 if (m_hWriteEvent != NULL ) CloseHandle(m_hWriteEvent); //关闭串口写事件句柄 TRACE("Thread ended\n"); delete[] m_szWriteBuffer; //释放发送缓冲区 }打开串口:
bool CMySerial::OpenSerial(CWnd* pParent, UINT portnr, UINT baud, CHAR parity,UINT databits, UINT stopbits, DWORD dwCommEvents, UINT writebuffersize) { assert(portnr > 0 && portnr < 5); assert(pParent != NULL); if (m_bThreadAlive) //如果串口监控程序处于激活态,那我们关闭它 { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread ended\n"); } if (m_ov.hEvent != NULL) //创建串口异步通信事件 ResetEvent(m_ov.hEvent); else m_ov.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if (m_hWriteEvent != NULL) //创建数据发送事件 ResetEvent(m_hWriteEvent); else m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL ); if (m_hShutdownEvent != NULL) //创建关闭串口事件 ResetEvent(m_hShutdownEvent); else m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //串口事件设定 及 优先级分配 m_hEventArray[0] = m_hShutdownEvent; //优先级最高 m_hEventArray[1] = m_ov.hEvent; m_hEventArray[2] = m_hWriteEvent; //初始化临界资源 InitializeCriticalSection(&m_csCommunicationSync); m_pParent = pParent; //保存串口操作窗口指针 if (m_szWriteBuffer != NULL) //为发送缓存清理空间 { delete[] m_szWriteBuffer; } m_szWriteBuffer = new char[writebuffersize]; //发送字符型的信息 m_nPortNr = portnr; //保存串口号 m_nWriteBufferSize = writebuffersize; //将要发送的数据 m_dwCommEvents = dwCommEvents; //串口事件 BOOL bResult = FALSE; char *szPort = new char[50]; //数据缓冲区 char *szBaud = new char[50]; EnterCriticalSection(&m_csCommunicationSync);//锁定临界变量 if (m_hComm != NULL) //确保串口处于关闭状态 { CloseHandle(m_hComm); m_hComm = NULL; } sprintf(szPort, "COM%d", portnr); //串口状态信息 sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits); //打开串口 m_hComm = CreateFile((LPCWSTR)szPort, //串口号 出现char*与LPCWSTR不兼容 强制转换 GENERIC_READ | //读模式 GENERIC_WRITE, //写模式 0, //必须为零 NULL, //安全型属性结构 OPEN_EXISTING, //必须置为此 FILE_FLAG_OVERLAPPED,//采用异步的输入输出形式 NULL); //必须为NULL if (m_hComm == INVALID_HANDLE_VALUE) {//串口打开失败 delete [] szPort; delete [] szBaud; return FALSE; } //设置超时参数 m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutConstant = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; if (SetCommTimeouts(m_hComm, &m_CommTimeouts))//设置串口参数 {//超时设置 if (SetCommMask(m_hComm, dwCommEvents)) {//事件设置 if (GetCommState(m_hComm, &m_dcb)) { //参数设置 m_dcb.EvtChar = 'q'; m_dcb.fRtsControl = RTS_CONTROL_ENABLE; if (BuildCommDCB((LPCWSTR)szBaud, &m_dcb)) { if (!SetCommState(m_hComm, &m_dcb)) ProcessErrorMessage("SetCommState()"); } else //串口参数设置失败 ProcessErrorMessage("BuildCommDCB()"); } else //参数获取失败 ProcessErrorMessage("GetCommState()"); } else//串口事件设置失败 ProcessErrorMessage("SetCommMask()"); } else//串口超时设置失败 ProcessErrorMessage("SetCommTimeouts()"); delete [] szPort; //清空数据区 delete [] szBaud; PurgeComm(m_hComm, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR); LeaveCriticalSection(&m_csCommunicationSync);//解锁临时变量 return TRUE; }
打开串口代码设计的核心思想为:
1.判断串口监控线程是否处于激活状态?如果是,那么需要将它关闭;
2.创建并启动串口的3个事件;
3.创建的事件句柄保存到事件数组里;
4.初始化临界资源;并申请一段数据发送缓存区;
5.保存传入的参数,并锁定临界资源;
6.验证串口是否已关闭?如果没有关闭,则要关闭;
7.打开串口,并判断是否打开串口成功?否则需要我们释放资源后返回;
8.设置串口通信的超时参数。
9.将前面准备好的串口的所有属性设置到串口上,设置失败后需要调用消息盒子进行失败处理。
10.释放资源,清空缓存区,并解锁临界资源,使得其它进程以后可以使用这个临界资源。
相关文章推荐
- 串口通信模块5:串口操作自定义类(2)
- 串口通信模块5:串口操作自定义类(3)
- MFC串口操作(异步方式)源码
- C#串口操作(国外网站看来的,共享一下)
- Win32串口操作的技巧
- C#串口操作
- 请问安装IVT软件后,USB蓝牙适配器在编程上可以当成串口操作吗?
- 在Java中操作串口实现短信收发
- 在Java中操作串口实现短信收发
- 【C#】串口操作实用类
- 【C#】串口操作实用类
- C#串口操作(国外网站看来的,共享一下)
- VB.Net 中的串口操作问题
- MFC串口操作(异步方式)源码
- 串口操作中的一个错误
- C#中的串口操作(最简单模式)
- 一个操作串口的类.
- 在Java中操作串口实现短信收发
- 以文件方式操作串口
- 请问安装IVT软件后,USB蓝牙适配器在编程上,可以当成串口操作吗?