CSerialPort类解析_第1页
CSerialPort类解析_第2页
CSerialPort类解析_第3页
CSerialPort类解析_第4页
CSerialPort类解析_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论