mfc的一個串口類

這幾天一直再看串口相關知識,對於其總結爲以下串口類:ide

頭文件聲明以下:函數

 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

對於上述代碼已編譯經過,可是具體的還未測試,等後續完善!this

謝謝支持!spa

相關文章
相關標籤/搜索