mfc的一个串口类

这几天一直再看串口相关知识,对于其总结为如下串口类:

头文件声明如下:

 1 #pragma once
 2 
 3 // 声明当串口接收到线程的时候调用的函数指针
 4 // 参数: 1,接收到的数据; 2,数据长度; 3,发送的目标地址
 5 typedef void (*DataArriveProc)(char *data, int len, DWORD dest);
 6 
 7 /***********************************
 8 1,实现一个串口类,用于进行串口的通信;
 9 2,其中的特性是,主动发送数据,被动接受
10   做出响应,其中开辟一个线程进型串口读取;
11 3,线程函数响应时,应该将接受到的数据转
12   发给使用此串口的上层应用;
13 ************************************/
14 class CSerialPort
15 {
16 public:
17     CSerialPort(void);
18     virtual ~CSerialPort(void);
19 
20     // 串口操作函数
21     BOOL OpenPort(LPCTSTR portName, DWORD baudRate, int dataBits, int stopBits, int parity, DataArriveProc proc, DWORD dest);
22     BOOL ClosePort();     // 关闭串口
23     DWORD WritePort(char *data, DWORD size);    // 往串口写数据
24 
25     // 串口读操作线程的操作函数
26     static UINT AFX_CDECL ReadPortProc(LPVOID lpParam);// 往串口读数据的线程函数
27     BOOL  Activate();   // 激活串口的读操作
28     BOOL  Deactivate(); // 取消串口的读操作
29     BOOL  IsActivate(); // 窗口是否已经准备好进行读操作
30 
31 private:
32     HANDLE m_hPortHandle; // 串口句柄
33     HANDLE m_hReadThread; // 读线程
34     BOOL   m_bReading;    // 读线程是否处于工作状态
35     DCB    m_dcbPort;     // 串口的工作参数
36     COMMTIMEOUTS m_tmOut; // 串口通信超时参数
37 
38     DataArriveProc m_pDataArriveProc; // 接收到数据后的调用的方法
39     DWORD m_dwDestAddress;  // 数据发送的目的地址
40 };
View Code

源文件定义如下:

  1 #include "StdAfx.h"
  2 #include "SerialPort.h"
  3 #include "Resource.h"
  4 
  5 CSerialPort::CSerialPort(void)
  6 {
  7     m_hPortHandle = INVALID_HANDLE_VALUE;
  8     m_hReadThread = INVALID_HANDLE_VALUE;
  9     m_bReading = FALSE;
 10 }
 11 
 12 CSerialPort::~CSerialPort(void)
 13 {
 14     if(INVALID_HANDLE_VALUE != m_hPortHandle){
 15         ClosePort();
 16     }
 17     if(INVALID_HANDLE_VALUE != m_hReadThread){
 18         Deactivate();
 19     }
 20 }
 21 
 22 // 打开串口
 23 // 1,打开串口文件;
 24 // 2,设置串口属性
 25 // 3,完成操作;
 26 BOOL CSerialPort::OpenPort(LPCTSTR portName, DWORD baudRate, int dataBits, int stopBits, int parity, DataArriveProc proc, DWORD dest)
 27 {
 28     if(INVALID_HANDLE_VALUE != m_hPortHandle){
 29         // 串口已经打开
 30         return TRUE;
 31     }
 32 
 33     CString temp;
 34 
 35     // 保存数据到达后的响应地址,及目的地
 36     m_pDataArriveProc = proc;
 37     m_dwDestAddress = dest;
 38 
 39     // 1, 打开串口文件
 40     m_hPortHandle = ::CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 41     if(INVALID_HANDLE_VALUE == m_hPortHandle){
 42         temp.LoadString(IDS_OPENPORT_FAIL);
 43         AfxMessageBox(temp);
 44         return FALSE;
 45     }
 46 
 47     // 2, 获取串口的工作参数并重新赋值
 48     GetCommState(m_hPortHandle, &m_dcbPort);
 49     m_dcbPort.BaudRate = baudRate; // 设置波特率(外部设置)
 50     m_dcbPort.ByteSize = dataBits; // 通信字节位数
 51     m_dcbPort.fParity = 1; // 奇偶校验使能,1可以
 52     m_dcbPort.Parity = parity; // 校验方式:外设
 53     m_dcbPort.StopBits = stopBits;// 停止位
 54     m_dcbPort.fBinary = 1;
 55     m_dcbPort.fDtrControl = 0;
 56     m_dcbPort.fRtsControl = 0;
 57     m_dcbPort.fOutX= m_dcbPort.fInX= m_dcbPort.fTXContinueOnXoff=0;
 58 
 59     // 3,设置一组监视串口设备的事件,什么信息到达时通知
 60     SetCommMask(m_hPortHandle, EV_RXCHAR);
 61     // 4,设置串口的通信参数,主要是缓冲区大小
 62     SetupComm(m_hPortHandle, 10240, 10240);
 63     // 5,设置工作参数
 64     if(!SetCommState(m_hPortHandle, &m_dcbPort)){
 65         temp.LoadString(IDS_SETSTATE_FAIL);
 66         AfxMessageBox(temp);
 67         ClosePort();
 68         return FALSE;
 69     }
 70 
 71     // 6,获取通信超时信息并重新设置
 72     GetCommTimeouts(m_hPortHandle, &m_tmOut);
 73     m_tmOut.ReadIntervalTimeout = 100;
 74     m_tmOut.ReadTotalTimeoutConstant = 100;
 75     m_tmOut.ReadTotalTimeoutMultiplier = 100;
 76     m_tmOut.WriteTotalTimeoutMultiplier = 100;
 77     m_tmOut.WriteTotalTimeoutConstant = 100;
 78     if(!SetCommTimeouts(m_hPortHandle, &m_tmOut)){
 79         temp.LoadString(IDS_SETTTMOUT_FAIL);
 80         AfxMessageBox(temp);
 81         ClosePort();
 82         return FALSE;
 83     }
 84 
 85     // 7,清空串口缓冲区
 86     PurgeComm(m_hPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
 87     return TRUE;
 88 }
 89 // 关闭串口
 90 // 1,清空通信设备监听事件;
 91 // 2,清空串口缓冲区;
 92 // 3,关闭串口文件句柄;
 93 BOOL CSerialPort::ClosePort()
 94 {
 95     if(INVALID_HANDLE_VALUE != m_hPortHandle){
 96         SetCommMask(m_hPortHandle, 0);
 97         PurgeComm(m_hPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
 98         CloseHandle(m_hPortHandle);
 99         m_hPortHandle = INVALID_HANDLE_VALUE;
100         return TRUE;
101     }
102 
103     return TRUE;
104 }
105 
106 // 往串口写数据
107 // 1,首先检查串口是否处于工作状态;
108 // 2,向串口写入内容;
109 // 3,返回写入的内容大小;
110 DWORD CSerialPort::WritePort(char *data, DWORD size)
111 {
112     if(INVALID_HANDLE_VALUE == m_hPortHandle){
113         return 0;
114     }
115 
116     DWORD writeLen = 0;
117     BOOL ret = FALSE;
118 
119     ret = WriteFile(m_hPortHandle, data, size*sizeof(char), &writeLen, NULL);
120 
121     return writeLen;
122 }
123 
124 // 激活串口的读操作
125 // 1,判断串口是否已经打开;
126 // 2,判断串口读线程是否已经创建;
127 // 3,设置成员变量;
128 BOOL CSerialPort::Activate()
129 {
130     if(INVALID_HANDLE_VALUE == m_hPortHandle){
131         return FALSE;
132     }
133     
134     if(!m_bReading){
135         m_hReadThread  = AfxBeginThread(ReadPortProc, this);
136         m_bReading = TRUE;
137     }
138 
139     if(INVALID_HANDLE_VALUE !=m_hReadThread){
140         // ResumeThread(m_hReadThread);
141         return TRUE;
142     }else{
143         m_bReading = FALSE;
144         return FALSE;
145     }
146     
147     return FALSE;
148 } 
149 // 取消串口的读操作
150 // 1, 判断串口是否已经打开;
151 // 2,判断读线程是否已经创建;
152 // 3,设置成员变量;
153 BOOL CSerialPort::Deactivate()
154 {
155     if(INVALID_HANDLE_VALUE == m_hPortHandle){
156         return FALSE;
157     }
158 
159     if(INVALID_HANDLE_VALUE == m_hReadThread){
160         return FALSE;
161     }
162 
163     if(m_bReading){
164         WaitForSingleObject(m_hReadThread, INFINITE);
165         CloseHandle(m_hReadThread);
166         m_hReadThread = INVALID_HANDLE_VALUE;
167         m_bReading = FALSE;
168         return TRUE;
169     }
170 
171     return FALSE;
172 }
173 // 窗口是否已经准备好进行读操作
174 BOOL CSerialPort::IsActivate()
175 {
176     return m_bReading;
177 }
178 
179 // 往串口读数据的线程函数
180 // 对于线程处理函数需要是一个全局的或者静态的
181 // 所以你需要知道你当前需要知道你用的是哪个串口
182 // 实例,顾此函数参数为串口实例指针
183 UINT CSerialPort::ReadPortProc(LPVOID lpParam)
184 {
185     // 1, 变量准备
186     CSerialPort *pPort = (CSerialPort*)lpParam;
187     CString temp;
188     char *buffer = NULL;
189     int buferSize = 512;
190     DWORD dwRead = 0;
191     BOOL  bRead = FALSE;
192 
193     // 2,基本条件判断
194     buffer = new char[buferSize];
195     while((pPort->m_hPortHandle != INVALID_HANDLE_VALUE) && (pPort->m_bReading)){       
196         bRead = ReadFile(pPort->m_hPortHandle, buffer, buferSize, &dwRead, NULL);
197         if(!bRead){
198             temp.LoadString(IDS_READFILE_FAIL);
199             AfxMessageBox(temp);
200         }else{
201             if(0 != dwRead)
202                 pPort->m_pDataArriveProc(buffer, buferSize, pPort->m_dwDestAddress);
203         }
204     }
205 
206     return 0;
207 }
View Code

对于上述代码已编译通过,但是具体的还未测试,等后续完善!

谢谢支持!

转载于:https://www.cnblogs.com/dhf-0214/p/3511090.html

猜你喜欢

转载自blog.csdn.net/weixin_34355881/article/details/93206571
今日推荐