版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、CSerialPort类解析CSerialPort类的功能及成员函数介绍CSerialPort类是免费提供的串口累,Codeguru是一个非常不错的源代码网站CSerialPort类支持线连接(非MODEM)的串口编程操作。CSerialPort类是基于多线程的,其工作流程如下:首先设置好串口参数,再开启串口检测工作线程,串口检测工作线程检测到串口接收到的数据、流控制事件或其他串口事件后,就以消息方式通知主程序,激发消息处理函数来进行数据处理,这是对接受数据而言的,发送数据可直接向串口发送。CSerialPort类定义的消息如表消息名称消息号功能说明WM_COMM_BREAK_DETECTED
2、WM_USER+1检测到输入中断WM_COMM_CTS_DETECTEDWM_USER+2检测到CTS(清除发送)信号状态改变WM_COMM_DSR_DETECTEDWM_USER+3检测到DSR(数据设备准备就绪)信号状态改变WM_COMM_ERR_DETECTEDWM_USER+4发生线状态错误(包括CE_FRAME,CE_OVERRUN,和CE_RXPARITY)WM_COMM_RING_DETECTEDWM_USER+5检测到响铃指示信号WM_COMM_RLSD_DETECTEDWM_USER+6检测到RLSD(接收线信号)状态改变WM_COMM_RXCHARWM_USER+7接收到一
3、个字符并已放入接受缓冲区WM_COMM_RXFLAG_DETECTEDWM_USER+8检测到接受到字符(该字符已放入接受缓冲区)事件WM_COMM_TXEMPTY_DETECTEDWM_USER+9检测到发送缓冲区最后一个字符已经被发送介绍几个经常用到的函数:1、串口初始化函数InitPortBOOL CSerialPort:InitPort(CWnd *pPortOwner, / the owner (CWnd) of the port (receives
4、 message) UINT portnr, / portnumber (1.4) &
5、#160; UINT baud, / baudrate &
6、#160; char parity, / parity &
7、#160; UINT databits, / databits
8、60; UINT stopbits, / stopbits DWORD
9、dwCommEvents, / EV_RXCHAR, EV_CTS etc UINT writebuffersize) /
10、 size to the writebuffer assert(portnr > 0 && portnr < 5); assert(pPortOwner != NULL); / if the thread is
11、160;alive: Kill if (m_bThreadAlive) do SetEvent
12、(m_hShutdownEvent); while (m_bThreadAlive); TRACE("Thread endedn");
13、; / create events if (m_ov.hEvent != NULL) ResetEvent(m_ov.hEvent); m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
14、60; if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if
15、(m_hShutdownEvent != NULL) ResetEvent(m_hShutdownEvent); m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); / initialize the ev
16、ent objects m_hEventArray0 = m_hShutdownEvent; / highest priority m_hEventArray1 = m_ov.hEvent; m_hEventArray2 = m_hWriteEvent;
17、 / initialize critical section InitializeCriticalSection(&m_csCommunicationSync); / set buffersize for writing and save the owner m
18、_pOwner = pPortOwner; if (m_szWriteBuffer != NULL) delete m_szWriteBuffer; m_szWriteBuffer = new charwritebuffersize;
19、60; m_nPortNr = portnr; m_nWriteBufferSize = writebuffersize; m_dwCommEvents = dwCommEvents; BOOL bResult = FALSE; &
20、#160;char *szPort = new char50; char *szBaud = new char50; / now it critical! EnterCriticalSection(&m_csCommunicationSync); &
21、#160; / if the port is already opened: close it if (m_hComm != NULL) CloseHandle(m_hComm);
22、160; m_hComm = NULL; / prepare port strings sprintf(szPort, "COM%d", portnr); sprintf(szBaud, "baud=%d par
23、ity=%c data=%d stop=%d", baud, parity, databits, stopbits); / get a handle to the port m_hComm = CreateFile(szPort,
24、0; / communication port string (COMX)
25、0; GENERIC_READ | GENERIC_WRITE, / read/write types 0, &
26、#160; / comm devices must be opened with exclusive access
27、 NULL, / no security at
28、tributes OPEN_EXISTING, /&
29、#160;comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED,
30、60; / Async I/O 0);
31、60; / template must be 0 for comm devices if (m_hComm = INVALID_HANDLE_VALUE) /
32、 port not found delete szPort; delete szBaud; return FALSE;
33、0; / set the timeout values m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.ReadTota
34、lTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; / configure if
35、0;(SetCommTimeouts(m_hComm, &m_CommTimeouts) if (SetCommMask(m_hComm, dwCommEvents) &
36、#160; if (GetCommState(m_hComm, &m_dcb) m_dcb.fRtsControl = RTS_CONTROL_ENABLE; &
37、#160; / set RTS bit high! if (BuildCommDCB(szBaud, &m_dcb)
38、 if (SetCommState(m_hComm, &m_dcb) &
39、#160; / normal operation. continue else
40、160; ProcessErrorMessage("SetCommState()");
41、160; else ProcessErrorMessage("BuildCommDCB()");
42、0; else ProcessErrorMessage("GetCommState()");
43、 else ProcessErrorMessage("SetCommMask()"); else ProcessErrorMessage(&qu
44、ot;SetCommTimeouts()"); delete szPort; delete szBaud; / flush the port PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXC
45、LEAR | PURGE_RXABORT | PURGE_TXABORT); / release critical section LeaveCriticalSection(&m_csCommunicationSync); TRACE("Initialisation for communica
46、tionport %d completed.nUse Startmonitor to communicate.n", portnr); return TRUE; 这个函数是用来初始化串口的,即设置串口的通信参数:需要打开的串口号、波特率、奇偶校验方式、数据位、停止位,这里还可 以用来进行事件的设定。如果串口初始化成功,就返回TRUE,若串口被其他设备占用、不存在或存在其他股占,就返回FALSE,编程者可以在这儿提示串口操作是
47、否成功。如果在当前主串口调用这个函数,那么pPortOwner可用this指针表示,串口号在函数中做了限制,只能用1,2,3和4四个串口号,而事实上在编程时可能用到更多串口号,可以通过通过注释掉本函数中的“assert(portur>0&&portnr<5)”语句取消对串口号的限制。2、启动串口通信监测线程函数StartMonitoring()串口初始化成功后,就可以调用BOOL StartMonitoring()来启动串口检测线程,线程启动成功,发挥TRUEBOOL CSerialPort:StartMonitoring()
48、0;if (!(m_Thread = AfxBeginThread(CommThread, this) return FALSE; TRACE("Thread startedn"); return TRUE; 3、暂停或停止监测线程函数StopMonitoring()该函数暂停或停止串口检测,要注意的是,调用该函数后,串口资源仍然被占用/ Suspend the comm thread / BO
49、OL CSerialPort:StopMonitoring() TRACE("Thread suspendedn"); m_Thread->SuspendThread(); return TRUE; 4、关闭串口函数ClosePort()该函数功能是关闭串口,释放串口资源,调用该函数后,如果要继续使
50、用串口,还需要调用InitPort()函数5、通过串口发送字符/写串口函数WriteToPort()该函数完成写串口功能,即向串口发送字符。/ Write a string to the port void CSerialPort:WriteToPort(char *string) assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer); strc
51、py(m_szWriteBuffer, string); / set event for write SetEvent(m_hWriteEvent); 以上是常用的函数介绍,熟悉该类的使用后,可以仔细看看其他函数,对上面介绍的函数,在对串口资源的使用上要记住一下三点:l 打开串口用调用InitPort()和StartMonitoring();关闭串口用StopMonitoring()和ClosePort()而且以上函数的调用顺序不能乱l 通过串口发送字符调用函数Write
52、ToPort()l 接受串口收到的字符需要自己编写WM_COMM_RXCHAR消息处理函数,需要手工添加。操作:首先,需要操作一个串口,所以只需要定义1个类对象就可以了,如要操作多个串口,则要为每个串口均定一个类对象,这可以通过数据方式来实现,这里定义的类对象为m_SerialPort,再定义一个布尔变量m_bSerialPortOpened用来标志串口是否打开。在CserialPort类中有多个串口事件可以响应,在一般串口编程中,只需要处理WM_COMM_RXCHAR消息就可以了,该类所有的消息均需要人工添加消息处理函数,将处理函数名定义为OnComm(),首先在SerialPor
53、tTestDlg.h(头文件)中添加串口字符接受消息WM_COMM_RXCHAR(串口接受缓冲区内有一个字符)的响应函数声明:/Generated message map funnctions /AFX_MSG(CSCportTestView) afx_msg long OnComm(WPARAM ch, LPARAM port); /AFX_MSG 然后在,SerilPortTestDlg.cpp文件中进行WM_COMM_RXCHAR消息映射BEGIN_MESS
54、AE_MAP(CSerialPortTestDlg, CDialog)s /AFX_MSG_MAP(CSerialPortTestDlg) ON_MESSAGE(WM_COMM_RXCHAR, OnComm) /AFX_MSG_MAP END_MESSAGE_MAP() 接着,在SerialPortTestDlg.cpp文件中加入函数OnComm()的实现,并在其中完成对节诶受到的字符的处理,将接收到的字符显示在接受编辑框中:long CSerialPortTestDlg:OnComm(WPARAM
55、160;ch, LPARAM port) m_strEditReceiveMsg += ch; UpdateData(FLASE);/将接收到的字符显示在接受编辑框中 returne 0; 说明:WPARAM、LPARAM类型是多态数据类型,在WIN32中为32位,支持多种数据类型,根据需要自动适应,这样,程序有很强的适应性,再次,我们可以分贝理解为char和integer类型数据,每当串口接受缓冲
56、区内有一个字符时,就会产生一个WM_COMM_RXCHAR消息,除法OnComm()函数,这时就可以在函数中进行数据处理,所以,这个消息就是整个程序的源头。虽然CSerialPort类是一个非常好的类,但毕竟只是集中了作者一个人的智慧和经验,他也有许多缺陷,n 原类只能发送字符(ASCII文本)不能处理二进制发送(也就是不能发送0X00)n 该类不能很好的释放串口n 存在内存泄漏可以进行如下改进改进一、ASCII文本和二进制数据发送方式兼容CSerialPort类中只有一个发送函数WriteToPort()/ / Write a
57、60;string to the port / void CSerialPort:WriteToPort(char *string) assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer); strcpy(m_szWriteBuffer, string
58、); / set event for write SetEvent(m_hWriteEvent); 调用上面的函数就只能用字符串方式,而c语言中,空字符(NULL,其中ASCII码值为0,即通常所说的十六禁止0x00字符),是串结束符,当检测到NULL字符后,就认为该字符串结束了,所以0x00字符以ASCII文本方式是不能从串口发送出去的,那么解决这一问题的方法就是用二进制发送,其实这里说的二进制,只不过是不以我们通常所说的“可见”或“
59、能显示的字符”发送,比如,要发如下的一组值:char chSend5=0x33,0x96,0x00,0x31,0xf1;下面来对类做一些改进,解决这个问题,原理就是用字符数据来发送数据,并在发送时指定其长度,这样,数据没有发送完,发送过程就不会停止,CSerialPort类是用API函数编写的在,只要在WriteFile()函数中指定其实际要发送的长度,就可以将数据全部发送出去:实现步骤如下:1、在SerialPort.h文件中为CSerialPort类添加一个整形public成员变量,:int m_nWriteSize;用于指定发送字符数据的长度添加三个发送函数h文件:c
60、pp view plaincopy1. #ifndef _SERIALPORT_H_ 2. #define _SERIALPORT_H_ 3. 4. #define WM_COMM_BREAK_DETECTED WM_USER+1 / A break was detected
61、 on input. 5. #define WM_COMM_CTS_DETECTED WM_USER+2 / The CTS (clear-to-send) signal changed state. 6. #define WM_COMM_DSR_DETECTED
62、160; WM_USER+3 / The DSR (data-set-ready) signal changed state. 7. #define WM_COMM_ERR_DETECTED WM_USER+4 / A
63、 line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 8. #define WM_COMM_RING_DETECTED WM_USER+5 / A ring
64、 indicator was detected. 9. #define WM_COMM_RLSD_DETECTED WM_USER+6 / The RLSD (receive-line-signal-detect) signal changed state. 10.
65、#define WM_COMM_RXCHAR WM_USER+7 / A character was received and placed in the input buffer. 11. #define&
66、#160;WM_COMM_RXFLAG_DETECTED WM_USER+8 / The event character was received and placed in the input buffer. 12. #define WM_COMM_TXEMPTY_DETECTE
67、D WM_USER+9 / The last character in the output buffer was sent. 13. 14. 15. class CSerialPort 16. 17. pu
68、blic: 18. void ClosePort(); 19. void WriteToPort(LPCTSTR string, int n); 20. void WriteToPort(LPCTSTR string); 21.
69、0; void WriteToPort(char *string, int n); 22. CSerialPort(); 23. virtual CSerialPort(); 24. BOOL
70、60; InitPort(CWnd *pPortOwner, / the owner (CWnd) of the port (receives message) 25.
71、; UINT portnr, / portnumber (1.4) 26.
72、0; UINT baud, / baudrate 27.
73、 char parity, / parity 28. UINT databits, &
74、#160; / databits 29. UINT stopbits,
75、;/ stopbits 30. DWORD dwCommEvents, / EV_RXCHAR, EV_CTS etc 31.
76、0; UINT writebuffersize); / size to the writebuffer 32. 33.
77、160; BOOL StartMonitoring(); 34. BOOL RestartMonitoring(); 35. BOOL
78、0;StopMonitoring(); 36. DWORD GetWriteBufferSize(); 37. DWORD GetCommEvents(); 38.
79、DCB GetDCB(); 39. 40. void WriteToPort(char *string); 41. int m_nWriteSi
80、ze; 42. 43. protected: 44. / protected memberfunctions 45. void ProcessErrorMessage(char *ErrorText); 46
81、. static UINT CommThread(LPVOID pParam); 47. static void ReceiveChar(CSerialPort *port, COMSTAT comstat); 48. static
82、160;void WriteChar(CSerialPort *port); 49. 50. / thread 51. CWinThread *m_Thread;
83、60;52. 53. / synchronisation objects 54. CRITICAL_SECTION m_csCommunicationSync; 55. BOOL
84、 m_bThreadAlive; 56. 57. / handles 58. HANDLE m_hShutdownEv
85、ent; 59. HANDLE m_hComm; 60. HANDLE
86、0; m_hWriteEvent; 61. 62. / Event array. 63. / One element is used for each event. There are two event handles for
87、each port. 64. / A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent). 65. / T
88、here is a general shutdown when the port is closed. 66. HANDLE m_hEventArray3; 67. 6
89、8. / structures 69. OVERLAPPED m_ov; 70. COMMTIMEOUTS m_CommTimeouts;
90、160; 71. DCB m_dcb; 72. 73. / owner window 74. &
91、#160; CWnd *m_pOwner; 75. 76. / misc 77. UINT
92、160; m_nPortNr; 78. char *m_szWriteBuffer; 79. DWORD
93、 m_dwCommEvents; 80. DWORD m_nWriteBufferSize; 81. ; 82.
94、160; 83. #endif _SERIALPORT_H_ cpp文件:cpp view plaincopy1. CSerialPort.cpp 2. /* 3. 4. * FILENAME CSerialPort.cpp 5. 6. * 7. 8. * PURPOSE This class can&
95、#160;read, write and watch one serial port. 9. 10. * It sends messages to its owner when something happends on the port 11. 12. * The class creates
96、160;a thread for reading and writing so the main 13. 14. * program is not blocked. 15. 16. * 17. 18. * CREATION DATE 15-09-1997 19. 2
97、0. * LAST MODIFICATION 12-11-1997 21. 22. * 23. 24. * AUTHOR Remon Spekreijse 25. 26. * 27. 28. * 29. 30. */ 31. 32.
98、60; 33. #include "stdafx.h" 34. 35. #include "CSerialPort.h" 36. 37. #include <assert.h> 38. 39. 40. / 41. &
99、#160; 42. / Constructor 43. 44. / 45. 46. CSerialPort:CSerialPort() 47. 48. 49. 50. m_hComm = NULL;
100、0; 51. 52. 53. / initialize overlapped structure members to zero 54. 55. m_ov.Offset = 0; 56. 57.
101、60; m_ov.OffsetHigh = 0; 58. 59. 60. / create events 61. 62. m_ov.hEvent = NULL; 63.
102、60;64. m_hWriteEvent = NULL; 65. 66. m_hShutdownEvent = NULL; 67. 68. 69. m_szWriteBuffer = NULL; &
103、#160;70. 71. 72. m_bThreadAlive = FALSE; 73. 74. 75. m_nWriteSize = 0; 76. 77. 78. &
104、#160; 79. 80. / 81. 82. / Delete dynamic memory 83. 84. / 85. 86. CSerialPort:CSerialPort() 87. 88. 89.
105、 90. do 91. 92. 93. 94. SetEvent(m_hShutdownEvent); 95. 96.
106、60; 97. while (m_bThreadAlive); 98. 99. 100. TRACE("Thread endedn"); 101. 102. 103. d
107、elete m_szWriteBuffer; 104. 105. 106. 107. 108. / 109. 110. / Initialize the port. This can be port 1 to 4.
108、160; 111. 112. / 113. 114. BOOL CSerialPort:InitPort(CWnd *pPortOwner, / the owner (CWnd) of the port (receives message) 115. 116.
109、60; UINT portnr, / portnumber (1.4) 117. 118.
110、160; UINT baud, / baudrate 119. 120.
111、0; char parity, / parity 121. 122.
112、 UINT databits, / databits 123. 124. UINT stopbits, / st
113、opbits 125. 126. DWORD dwCommEvents, / EV_RXCHAR, EV_CTS etc
114、127. 128. UINT writebuffersize) / size to the writebuffer 129.
115、0; 130. 131. 132. assert(portnr > 0 && portnr < 5); 133. 134. assert(pPortOwner != NULL); 135.
116、0; 136. 137. / if the thread is alive: Kill 138. 139. if (m_bThreadAlive) 140. 141.
117、0; 142. 143. do 144. 145. 146. 147. Se
118、tEvent(m_hShutdownEvent); 148. 149. 150. while (m_bThreadAlive); 151. 152.
119、 TRACE("Thread endedn"); 153. 154. 155. 156. 157. / create events 158. 159.
120、0; if (m_ov.hEvent != NULL) 160. 161. ResetEvent(m_ov.hEvent); 162. 163. else 164. 165.
121、60; m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 166. 167. 168. if (m_hWriteEvent != NULL) 169. 170.
122、; ResetEvent(m_hWriteEvent); 171. 172. else 173. 174. m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE,
123、60;NULL); 175. 176. 177. if (m_hShutdownEvent != NULL) 178. 179. ResetEvent(m_hShutdownEvent); 180.
124、160; 181. else 182. 183. m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 184. 185. 186. &
125、#160; / initialize the event objects 187. 188. m_hEventArray0 = m_hShutdownEvent; / highest priority 189. 190. m_hEventArray1 =
126、 m_ov.hEvent; 191. 192. m_hEventArray2 = m_hWriteEvent; 193. 194. 195. / initialize critical section 196.
127、; 197. InitializeCriticalSection(&m_csCommunicationSync); 198. 199. 200. / set buffersize for writing and save the owner 201. &
128、#160; 202. m_pOwner = pPortOwner; 203. 204. 205. if (m_szWriteBuffer != NULL) 206. 207.
129、0;delete m_szWriteBuffer; 208. 209. m_szWriteBuffer = new charwritebuffersize; 210. 211. 212. m_nPortNr = portnr;
130、60;213. 214. 215. m_nWriteBufferSize = writebuffersize; 216. 217. m_dwCommEvents = dwCommEvents; 218. 219. 2
131、20. BOOL bResult = FALSE; 221. 222. char *szPort = new char50; 223. 224. char *szBaud = new char50; 225. 226. 227. / now it critical! 228. 229.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 湖南文理学院《复变函数》2022-2023学年第一学期期末试卷
- 湖南工业大学科技学院《数字逻辑与数字系统》2021-2022学年第一学期期末试卷
- 海南省2023-2024学年高三上学期11月学业水平诊断(一)物理试题 含答案
- 妇幼保健院开展安全生产整治行动实施方案
- 第3章第1节 细胞膜的结构与功能-2022年初升高生物无忧衔接(人教版2019)(解析版)
- 【++初中语文+】第24课《愚公移山》课件+统编版语文八年级上册
- 继电保护员(220kV及以下)机考题库及答案解析
- 2024至2030年中国小学生包行业投资前景及策略咨询研究报告
- 2024至2030年中国骨架兰尼铜催化剂行业投资前景及策略咨询研究报告
- 2024至2030年中国锌合金手链行业投资前景及策略咨询研究报告
- 带状疱疹入院记录、病程、沟通病历书写模板
- 隐患排查记录表(液化气站)
- 电子病历六级评审实践分享课件
- XX(单位)因私出国(境)证照管理登记表
- DB34T 4307.1-2022+内河水下工程结构物检测与评定技术规范+第1部分:桥梁部分-(高清正版)
- 模拟电子技术基础期末复习题
- 三位数乘一位数练习题(300道)
- 种业市场营销大全课件
- 基本公共卫生服务项目工作存在问题整改情况汇报【六篇】
- 《毛主席在花山》-完整版课件
- 西游记 品味经典名著导读PPT
评论
0/150
提交评论