串口类的编写
CSerial類只有2個文件,分別是CSerial.cpp和CSerial.h。
?
CSerial.h內(nèi)容如下:
?
1 /***************************************************2 *作 者:溫子祺
3 *聯(lián)系方式:wenziqi@hotmail.com
4 *說 明:CSerial.h
5 提供外部調(diào)用的函數(shù)
6 Open(),Close(),Send()
7 接收數(shù)據(jù)時通過消息來實現(xiàn)
8 ***************************************************/
9 #ifndef __CSERIAL_H__
10 ?#define __CSERIAL_H__
11 ?#pragma once
12
13 ?class CSerial
14 {
15 ?public:
16 CSerial(void);
17 virtual~CSerial(void);
18
19 BOOL Open(CWnd *pPortOwner,
20 UINT portnr,
21 UINT baud,
22 UINT parity,
23 UINT databits,
24 UINT stopbits,
25 UINT rxdmsg);
26
27 BOOL Close(void);
28
29 UINT Send(UCHAR *pbuf,UINT len);
30
31 ?protected:
32
33 BOOL Ready(void) const;
34 BOOL CreateThreadAndEvent(void);
35 ?static
36 DWORD RecvThread(LPVOID lpArg);
37
38 private:
39 CWnd * m_pOwner;
40 BOOL m_bInit;
41
42 HANDLE m_hSerial;
43 HANDLE m_hRecvEvent;
44 HANDLE m_hRecvExitEvent;
45
46 UINT m_unRxdMsg;
47 };
48 #endif
?
CSerial.cpp代碼如下:
?
1 /***************************************************2 *作 者:溫子祺
3 *聯(lián)系方式:wenziqi@hotmail.com
4 *說 明:CSerial.cpp
5 提供外部調(diào)用的函數(shù)
6 Open(),Close(),Send()
7 接收數(shù)據(jù)時通過消息來實現(xiàn)
8 ***************************************************/
9 #include "StdAfx.h"
10 #include "CSerial.h"
11 #include <assert.h> //使用斷言
12
13 CSerial::CSerial(void)
14 {
15 m_pOwner=NULL;
16 m_bInit=FALSE;
17 m_hRecvEvent=NULL;
18 m_hRecvExitEvent=NULL;
19 m_hSerial=NULL;
20 m_bInit=FALSE;
21 }
22
23 CSerial::~CSerial(void)
24 {
25 Close();
26 }
27
28 BOOL CSerial::Ready(void)const
29 {
30 return m_bInit;
31 }
32
33 BOOL CSerial::Close(void)
34 {
35
36 if (m_hSerial)
37 {
38 CloseHandle(m_hSerial);
39 m_hSerial=NULL;
40 }
41
42 if (m_hRecvEvent)
43 {
44 CloseHandle(m_hRecvEvent);
45 m_hRecvEvent=NULL;
46 }
47
48 if (m_hRecvExitEvent)
49 {
50 SetEvent(m_hRecvExitEvent); //退出線程
51 Sleep(10);
52 CloseHandle(m_hRecvExitEvent);
53 m_hRecvExitEvent=NULL;
54 }
55
56 if (m_bInit)
57 {
58 m_bInit=FALSE;
59 }
60
61 if (m_pOwner)
62 {
63 m_pOwner=NULL;
64 }
65
66 return TRUE;
67 }
68
69 BOOL CSerial::Open(CWnd *pPortOwner,
70 UINT portnr,
71 UINT baud,
72 UINT parity,
73 UINT databits,
74 UINT stopbits,
75 UINT rxdmsg)
76 {
77 assert(NULL != pPortOwner);
78
79 m_pOwner = pPortOwner;
80
81 if (Ready())
82 {
83 Close();
84 }
85
86 COMMTIMEOUTS CommTimeOuts;
87 DCB dcb;
88
89 LPSTR sz= new CHAR[64];
90 LPWSTR wsz= new WCHAR[64];
91
92 // 打開串口
93 //wprintf_s(wsz,64,"COM%d",portnr);//用wprintf無效
94 sprintf_s(sz,64,"COM%d",portnr);
95 MultiByteToWideChar(CP_ACP,
96 0,
97 sz,
98 64,
99 wsz,
100 64);
101
102 m_hSerial = CreateFile(wsz,
103 GENERIC_READ | GENERIC_WRITE,
104 0,
105 0,
106 OPEN_EXISTING,
107 0,
108 0);
109
110 delete []sz;
111 delete []wsz;
112
113 if(m_hSerial == INVALID_HANDLE_VALUE)
114 {
115 return FALSE;
116 }
117
118 GetCommState(m_hSerial, &dcb); /* 讀取串口的DCB */
119 dcb.BaudRate = baud; //波特率
120 dcb.ByteSize = databits; //數(shù)據(jù)位
121 dcb.Parity = parity; //校驗位
122 dcb.StopBits = stopbits; //停止位
123
124 dcb.fParity = FALSE; /* 禁止奇偶校驗 */
125 dcb.fBinary = TRUE;
126 dcb.fDtrControl = 0; /* 禁止流量控制 */
127 dcb.fRtsControl = 0;
128 dcb.fOutX = 0;
129 dcb.fInX = 0;
130 dcb.fTXContinueOnXoff = 0;
131 dcb.EvtChar='q'; // 這個一定要,否則大于127的數(shù)值會接收不了啊
132
133 //設(shè)置狀態(tài)參數(shù)
134 SetCommMask(m_hSerial, EV_RXFLAG|EV_RXCHAR); /* 串口事件:接收到一個字符 */
135 SetupComm(m_hSerial, 1024, 1024); /* 設(shè)置接收與發(fā)送的緩沖區(qū)大小 */
136
137 if(!SetCommState(m_hSerial, &dcb)) /* 設(shè)置串口的DCB */
138 {
139 return FALSE;
140 }
141
142 //設(shè)置超時參數(shù)
143 GetCommTimeouts(m_hSerial, &CommTimeOuts);
144 CommTimeOuts.ReadIntervalTimeout = 100; /* 接收字符間最大時間間隔 */
145 CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
146 CommTimeOuts.ReadTotalTimeoutConstant = 100; /* 讀數(shù)據(jù)總超時常量 */
147 CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
148 CommTimeOuts.WriteTotalTimeoutConstant = 0;
149
150 if(!SetCommTimeouts(m_hSerial, &CommTimeOuts))
151 {
152 return FALSE;
153 }
154
155 PurgeComm(m_hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); /* 清除收/發(fā)緩沖區(qū) */
156
157 if (!CreateThreadAndEvent())
158 {
159 return FALSE;
160 }
161
162 m_unRxdMsg=rxdmsg;
163
164 m_bInit = TRUE;
165
166 return TRUE;
167 }
168 BOOL CSerial::CreateThreadAndEvent(void)
169 {
170 m_hRecvExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 創(chuàng)建串口接收線程退出事件*/
171
172 if (NULL==m_hRecvExitEvent)
173 {
174 return FALSE;
175 }
176
177 ResetEvent(m_hRecvExitEvent); //設(shè)置線程沒有退出
178
179 HANDLE hRecvThread=NULL;
180 DWORD dwThreadID =0;
181
182 // 創(chuàng)建串口接收線程
183 hRecvThread=CreateThread(0,
184 0,
185 (LPTHREAD_START_ROUTINE)RecvThread,
186 this,
187 0,
188 &dwThreadID);
189
190 if (NULL==hRecvThread)
191 {
192 return FALSE;
193 }
194
195 CloseHandle(hRecvThread);
196 hRecvThread=NULL;
197
198 return TRUE;
199 }
200
201 UINT CSerial::Send(UCHAR *pbuf,UINT len)
202 {
203 if (!Ready())
204 {
205 //AfxMessageBox(_T("請確保串口已正常打開"));
206 return 0;
207 }
208
209 BOOL rt=FALSE;
210
211 DWORD dwBytesSend=0,dwCnt=0;
212
213 while (len>dwCnt)
214 {
215 rt=WriteFile(m_hSerial,pbuf+dwCnt,len-dwCnt,&dwBytesSend,NULL);
216
217 if (!rt)
218 {
219 return FALSE;
220 }
221
222 dwCnt+=dwBytesSend;
223
224 if (len > dwCnt)
225 {
226 Sleep(100); //有可能I/O掛起
227 }
228 }
229
230 return (UINT)dwCnt;
231 }
232
233 DWORD CSerial::RecvThread(LPVOID lpArg)
234 {
235
236 assert(NULL != lpArg);
237
238 CSerial *pArg=(CSerial *)lpArg;
239
240 assert(NULL != pArg);
241
242 DWORD dwBytesRecv=0;
243 DWORD dwError=0;
244 UCHAR ucDat=0;
245 COMSTAT ComStat;
246
247 memset(&ComStat,0,sizeof(ComStat));
248
249 while (1)
250 {
251 if (WaitForSingleObject(pArg->m_hRecvExitEvent,0)==WAIT_OBJECT_0)
252 {
253 break; //線程退出
254 }
255
256 if (pArg->Ready())
257 {
258 ClearCommError(pArg->m_hSerial,&dwError,&ComStat);
259
260 if (0 == ComStat.cbInQue)
261 {
262 Sleep(1);
263 continue;
264 }
265
266 if (ReadFile(pArg->m_hSerial,&ucDat,1,&dwBytesRecv,NULL))
267 {
268 if (dwBytesRecv)
269 {
270 ::SendMessage((pArg->m_pOwner)->m_hWnd,
271 pArg->m_unRxdMsg,
272 (WPARAM)ucDat,
273 NULL);
274 }
275 }
276 }
277
278 Sleep(1);
279
280 }
281
282 Sleep(10); //讓線程安全退出
283
284 return 0;
285 }
286
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/wenziqi/archive/2010/07/01/1769156.html
總結(jié)
- 上一篇: linux下常用压缩格式的压缩与解压方法
- 下一篇: 谈搜索架构师的不同阶段