串口通信

这里采用字符串池实现串口数据接收,串口类改自一个老外写的CSerialPort类。

  1. /* 
  2. **  FILENAME            CSerialPort.h 
  3. ** 
  4. **  PURPOSE             This class can read, write and watch one serial port. 
  5. **                      It sends messages to its owner when something happends on the port 
  6. **                      The class creates a thread for reading and writing so the main 
  7. **                      program is not blocked. 
  8. ** 
  9. **  CREATION DATE       15-09-1997 
  10. **  LAST MODIFICATION   12-11-1997 
  11. ** 
  12. **  AUTHOR              Remon Spekreijse 
  13. ** 
  14. ** 
  15. */  
  16. #include "stringpool.h"  
  17.   
  18. #ifndef __SERIALPORT_H__  
  19. #define __SERIALPORT_H__  
  20.   
  21. #define WM_COMM_BREAK_DETECTED      WM_USER+1   // A break was detected on input.  
  22. #define WM_COMM_CTS_DETECTED        WM_USER+2   // The CTS (clear-to-send) signal changed state.   
  23. #define WM_COMM_DSR_DETECTED        WM_USER+3   // The DSR (data-set-ready) signal changed state.   
  24. #define WM_COMM_ERR_DETECTED        WM_USER+4   // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.   
  25. #define WM_COMM_RING_DETECTED       WM_USER+5   // A ring indicator was detected.   
  26. #define WM_COMM_RLSD_DETECTED       WM_USER+6   // The RLSD (receive-line-signal-detect) signal changed state.   
  27. #define WM_COMM_RXCHAR              WM_USER+7   // A character was received and placed in the input buffer.   
  28. #define WM_COMM_RXFLAG_DETECTED     WM_USER+8   // The event character was received and placed in the input buffer.    
  29. #define WM_COMM_TXEMPTY_DETECTED    WM_USER+9   // The last character in the output buffer was sent.    
  30.   
  31. class CSerialPort  
  32. {                                                          
  33. public:  
  34.     // contruction and destruction  
  35.     CSerialPort();  
  36.     virtual     ~CSerialPort();  
  37.   
  38.     // port initialisation                                            
  39.     BOOL        InitPort(CWinThread* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity = 'N'UINT databits = 8, UINT stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR | EV_CTS, UINT nBufferSize = 512);  
  40.   
  41.     // start/stop comm watching  
  42.     BOOL        StartMonitoring();  
  43.     BOOL        RestartMonitoring();  
  44.     BOOL        StopMonitoring();  
  45.   
  46.     DWORD       GetWriteBufferSize();  
  47.     DWORD       GetCommEvents();  
  48.     DCB         GetDCB();  
  49.     std::string *GetFrontString();  
  50.   
  51.     void        WriteToPort(char* string);  
  52.   
  53. protected:  
  54.     // protected memberfunctions  
  55.     void        ProcessErrorMessage(char* ErrorText);  
  56.     static UINT CommThread(LPVOID pParam);  
  57.     static void ReceiveChar(CSerialPort* port, COMSTAT comstat);  
  58.     static void WriteChar(CSerialPort* port);  
  59.   
  60.     // thread  
  61.     CWinThread*         m_Thread;  
  62.   
  63.     // synchronisation objects  
  64.     CRITICAL_SECTION    m_csCommunicationSync;  
  65.     CRITICAL_SECTION m_csQueLock;       //队列锁  
  66.     BOOL                m_bThreadAlive;  
  67.   
  68.     //事件对象  
  69.     HANDLE              m_hShutdownEvent;  
  70.     HANDLE              m_hComm;  
  71.     HANDLE              m_hWriteEvent;  
  72.     HANDLE              m_hEventArray[3];  
  73.       
  74.     // structures  
  75.     OVERLAPPED          m_ov;  
  76.     COMMTIMEOUTS        m_CommTimeouts;  
  77.     DCB                 m_dcb;  
  78.   
  79. public:  
  80.     CWinThread*             m_pOwner;  
  81.     StringPool *m_pStringPool;  
  82.     // misc  
  83.     UINT                m_nPortNr;  
  84.     char*               m_szWriteBuffer;  
  85.     DWORD               m_dwCommEvents;  
  86.     DWORD               m_nWriteBufferSize;  
  87.     UINT                m_nDataLen;  
  88.     queue<string *> m_strQue;         //字符串接收队列  
  89. };  
  90.   
  91. #endif __SERIALPORT_H__  
/*
**	FILENAME			CSerialPort.h
**
**	PURPOSE				This class can read, write and watch one serial port.
**						It sends messages to its owner when something happends on the port
**						The class creates a thread for reading and writing so the main
**						program is not blocked.
**
**	CREATION DATE		15-09-1997
**	LAST MODIFICATION	12-11-1997
**
**	AUTHOR				Remon Spekreijse
**
**
*/
#include "stringpool.h"

#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__

#define WM_COMM_BREAK_DETECTED		WM_USER+1	// A break was detected on input.
#define WM_COMM_CTS_DETECTED		WM_USER+2	// The CTS (clear-to-send) signal changed state. 
#define WM_COMM_DSR_DETECTED		WM_USER+3	// The DSR (data-set-ready) signal changed state. 
#define WM_COMM_ERR_DETECTED		WM_USER+4	// A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 
#define WM_COMM_RING_DETECTED		WM_USER+5	// A ring indicator was detected. 
#define WM_COMM_RLSD_DETECTED		WM_USER+6	// The RLSD (receive-line-signal-detect) signal changed state. 
#define WM_COMM_RXCHAR				WM_USER+7	// A character was received and placed in the input buffer. 
#define WM_COMM_RXFLAG_DETECTED		WM_USER+8	// The event character was received and placed in the input buffer.  
#define WM_COMM_TXEMPTY_DETECTED	WM_USER+9	// The last character in the output buffer was sent.  

class CSerialPort
{														 
public:
	// contruction and destruction
	CSerialPort();
	virtual		~CSerialPort();

	// port initialisation											
	BOOL		InitPort(CWinThread* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity = 'N', UINT databits = 8, UINT stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR | EV_CTS, UINT nBufferSize = 512);

	// start/stop comm watching
	BOOL		StartMonitoring();
	BOOL		RestartMonitoring();
	BOOL		StopMonitoring();

	DWORD		GetWriteBufferSize();
	DWORD		GetCommEvents();
	DCB			GetDCB();
	std::string *GetFrontString();

	void		WriteToPort(char* string);

protected:
	// protected memberfunctions
	void		ProcessErrorMessage(char* ErrorText);
	static UINT	CommThread(LPVOID pParam);
	static void	ReceiveChar(CSerialPort* port, COMSTAT comstat);
	static void	WriteChar(CSerialPort* port);

	// thread
	CWinThread*			m_Thread;

	// synchronisation objects
	CRITICAL_SECTION	m_csCommunicationSync;
	CRITICAL_SECTION m_csQueLock;		//队列锁
	BOOL				m_bThreadAlive;

	//事件对象
	HANDLE				m_hShutdownEvent;
	HANDLE				m_hComm;
	HANDLE				m_hWriteEvent;
	HANDLE				m_hEventArray[3];
	
	// structures
	OVERLAPPED			m_ov;
	COMMTIMEOUTS		m_CommTimeouts;
	DCB					m_dcb;

public:
	CWinThread*				m_pOwner;
	StringPool *m_pStringPool;
	// misc
	UINT				m_nPortNr;
	char*				m_szWriteBuffer;
	DWORD				m_dwCommEvents;
	DWORD				m_nWriteBufferSize;
	UINT				m_nDataLen;
	queue<string *> m_strQue;			//字符串接收队列
};

#endif __SERIALPORT_H__


  1. /* 
  2. **  FILENAME            CSerialPort.cpp 
  3. ** 
  4. **  PURPOSE             This class can read, write and watch one serial port. 
  5. **                      It sends messages to its owner when something happends on the port 
  6. **                      The class creates a thread for reading and writing so the main 
  7. **                      program is not blocked. 
  8. ** 
  9. **  CREATION DATE       15-09-1997 
  10. **  LAST MODIFICATION   12-11-1997 
  11. ** 
  12. **  AUTHOR              Remon Spekreijse 
  13. ** 
  14. ** 
  15. */  
  16.   
  17. #include "stdafx.h"  
  18. #include "SerialPort.h"  
  19.   
  20. #include <assert.h>  
  21.   
  22. //  
  23. // Constructor  
  24. //  
  25. CSerialPort::CSerialPort()  
  26. {  
  27.     m_hComm = NULL;  
  28.   
  29.     // initialize overlapped structure members to zero  
  30.     m_ov.Offset = 0;  
  31.     m_ov.OffsetHigh = 0;  
  32.   
  33.     // create events  
  34.     m_ov.hEvent = NULL;  
  35.     m_hWriteEvent = NULL;  
  36.     m_hShutdownEvent = NULL;  
  37.   
  38.     m_szWriteBuffer = NULL;  
  39.   
  40.     m_bThreadAlive = FALSE;  
  41. }  
  42.   
  43. //  
  44. // Delete dynamic memory  
  45. //  
  46. CSerialPort::~CSerialPort()  
  47. {  
  48.     do  
  49.     {  
  50.         SetEvent(m_hShutdownEvent);  
  51.     } while (m_bThreadAlive);  
  52.   
  53.     TRACE("Thread ended\n");  
  54.   
  55.     delete [] m_szWriteBuffer;  
  56. }  
  57.   
  58. //  
  59. // Initialize the port. This can be port 1 to 4.  
  60. //  
  61. BOOL CSerialPort::InitPort(CWinThread* pPortOwner,  // the owner (CWinTread) of the port (receives message)  
  62.                            UINT  portnr,        //端口号  
  63.                            UINT  baud,          //波特率  
  64.                            char  parity,        //奇偶校验位  
  65.                            UINT  databits,      //数据位   
  66.                            UINT  stopbits,      // 停止位  
  67.                            DWORD dwCommEvents,  // 准备监视的串口事件掩码  
  68.                            UINT  writebuffersize)   // 写缓冲区大小  
  69. {  
  70.     assert(portnr > 0 && portnr < 5);  
  71.     assert(pPortOwner != NULL);  
  72.   
  73.     //判断线程是否启动,否则结束线程  
  74.     if (m_bThreadAlive)  
  75.     {  
  76.         do  
  77.         {  
  78.             SetEvent(m_hShutdownEvent);  
  79.         } while (m_bThreadAlive);  
  80.         TRACE("Thread ended\n");  
  81.     }  
  82.   
  83.     //重叠事件对象  
  84.     if (m_ov.hEvent != NULL)  
  85.         ResetEvent(m_ov.hEvent);  
  86.     m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  87.       
  88.     //写事件对象  
  89.     if (m_hWriteEvent != NULL)  
  90.         ResetEvent(m_hWriteEvent);  
  91.     m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  92.   
  93.     //线程退出事件对象,有信号则线程退出  
  94.     if (m_hShutdownEvent != NULL)  
  95.         ResetEvent(m_hShutdownEvent);  
  96.     m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
  97.   
  98.     // initialize the event objects  
  99.     m_hEventArray[0] = m_hShutdownEvent;    // highest priority  
  100.     m_hEventArray[1] = m_ov.hEvent;  
  101.     m_hEventArray[2] = m_hWriteEvent;  
  102.   
  103.     InitializeCriticalSection(&m_csCommunicationSync);  
  104.     InitializeCriticalSection(&m_csQueLock);  
  105.   
  106.     // set buffersize for writing and save the owner  
  107.     m_pOwner = pPortOwner;  
  108.     m_pStringPool = new StringPool;  
  109.   
  110.     if (m_szWriteBuffer != NULL)  
  111.         delete [] m_szWriteBuffer;  
  112.     m_szWriteBuffer = new char[writebuffersize];  
  113.   
  114.     m_nPortNr = portnr;  
  115.   
  116.     m_nWriteBufferSize = writebuffersize;  
  117.     m_dwCommEvents = dwCommEvents;  
  118.     m_nDataLen = 15;  
  119.   
  120.     BOOL bResult = FALSE;  
  121.     char *szPort = new char[50];  
  122.     char *szBaud = new char[50];  
  123.   
  124.     //锁住串口,防止对同一串口进行操作  
  125.     EnterCriticalSection(&m_csCommunicationSync);  
  126.   
  127.     if (m_hComm != NULL)  
  128.     {  
  129.         CloseHandle(m_hComm);  
  130.         m_hComm = NULL;  
  131.     }  
  132.   
  133.     //串口连接字符串  
  134.     sprintf(szPort, "COM%d", portnr);  
  135.     sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);  
  136.   
  137.     //打开串口  
  138.     m_hComm = CreateFileA(szPort,                       //串口号  
  139.                          GENERIC_READ | GENERIC_WRITE,  // 允许读写  
  140.                          0,                             // 以独占模式打开  
  141.                          NULL,                          // 无安全属性  
  142.                          OPEN_EXISTING,                 // 通讯设备已存在  
  143.                          FILE_FLAG_OVERLAPPED,          // 异步IO  
  144.                          0);                            //通讯设备不能用模板打开  
  145.   
  146.     if (m_hComm == INVALID_HANDLE_VALUE)  
  147.     {  
  148.         // 串口未找到  
  149.         delete [] szPort;  
  150.         delete [] szBaud;  
  151.   
  152.         return FALSE;  
  153.     }  
  154.   
  155.     // 设置超时值  
  156.     m_CommTimeouts.ReadIntervalTimeout = 1000;  
  157.     m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;  
  158.     m_CommTimeouts.ReadTotalTimeoutConstant = 1000;  
  159.     m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;  
  160.     m_CommTimeouts.WriteTotalTimeoutConstant = 1000;  
  161.   
  162.     if (SetCommTimeouts(m_hComm, &m_CommTimeouts))  
  163.     {         
  164.         //设置串口要监视的事件  
  165.         if (SetCommMask(m_hComm, dwCommEvents))  
  166.         {  
  167.             //读取串口配置  
  168.             if (GetCommState(m_hComm, &m_dcb))  
  169.             {  
  170.                 m_dcb.fRtsControl = RTS_CONTROL_ENABLE;     // set RTS bit high!  
  171.                 //连接串口  
  172.                 if (BuildCommDCBA(szBaud, &m_dcb))  
  173.                 {  
  174.                     //修改串口配置  
  175.                     if (SetCommState(m_hComm, &m_dcb))  
  176.                         ; // normal operation... continue  
  177.                     else  
  178.                         ProcessErrorMessage("SetCommState()");  
  179.                 }  
  180.                 else  
  181.                     ProcessErrorMessage("BuildCommDCB()");  
  182.             }  
  183.             else  
  184.                 ProcessErrorMessage("GetCommState()");  
  185.         }  
  186.         else  
  187.             ProcessErrorMessage("SetCommMask()");  
  188.     }  
  189.     else  
  190.         ProcessErrorMessage("SetCommTimeouts()");  
  191.   
  192.     delete [] szPort;  
  193.     delete [] szBaud;  
  194.   
  195.     // 清空缓冲区  
  196.     PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  197.   
  198.     LeaveCriticalSection(&m_csCommunicationSync);  
  199.   
  200.     TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);  
  201.   
  202.     return TRUE;  
  203. }  
  204.   
  205. UINT CSerialPort::CommThread(LPVOID pParam)  
  206. {  
  207.     CSerialPort *port = (CSerialPort*)pParam;  
  208.       
  209.     //串口线程运行标志  
  210.     port->m_bThreadAlive = TRUE;   
  211.           
  212.     DWORD BytesTransfered = 0;   
  213.     DWORD Event = 0;  
  214.     DWORD CommEvent = 0;  
  215.     DWORD dwError = 0;  
  216.     COMSTAT comstat;  
  217.     BOOL  bResult = TRUE;  
  218.           
  219.     //检查串口是否打开  
  220.     if (port->m_hComm)         
  221.         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  222.   
  223.     //初始化COMSTAT  
  224.     ClearCommError(port->m_hComm, &dwError, &comstat);  
  225.     for (;;)   
  226.     {   
  227.         //等待串口事件发生,异步操作直接返回  
  228.         bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);  
  229.   
  230.         if (!bResult)    
  231.         {   
  232.             //错误处理  
  233.             switch (dwError = GetLastError())   
  234.             {   
  235.             case ERROR_IO_PENDING:    
  236.                 {   
  237.                     break;  
  238.                 }  
  239.             case 87:  
  240.                 {  
  241.                     //特殊处理  
  242.                     break;  
  243.                 }  
  244.             default:  
  245.                 {  
  246.                     port->ProcessErrorMessage("WaitCommEvent()");  
  247.                     break;  
  248.                 }  
  249.             }  
  250.         }  
  251.         //正常处理  
  252.         else  
  253.         {  
  254.             //清除串口的通信错误,返回当前的错误状态  
  255.             bResult = ClearCommError(port->m_hComm, &dwError, &comstat);  
  256.               
  257.             //串口未发送数据  
  258.             if (comstat.cbInQue == 0)  
  259.                 continue;  
  260.         }  
  261.       
  262.         //等待串口事件发生  
  263.         Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);  
  264.   
  265.         switch (Event)  
  266.         {  
  267.         case 0:  
  268.             {  
  269.                 //0号事件对象拥有高优先权,会优先到达  
  270.                 port->m_bThreadAlive = FALSE;  
  271.   
  272.                 //线程直接退出  
  273.                 AfxEndThread(100);  
  274.                 break;  
  275.             }  
  276.         case 1: // 读事件  
  277.             {  
  278.                 //读取串口事件掩码  
  279.                 GetCommMask(port->m_hComm, &CommEvent);  
  280.   
  281.                 if (CommEvent & EV_CTS)//CTS信号状态发生变化  
  282.                     ::PostThreadMessage(port->m_pOwner->m_nThreadID, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);  
  283.                 if (CommEvent & EV_RXFLAG)//接收到事件字符,并置于输入缓冲区中   
  284.                     ::PostThreadMessage(port->m_pOwner->m_nThreadID, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);  
  285.                 if (CommEvent & EV_BREAK) //输入中发生中断  
  286.                     ::PostThreadMessage(port->m_pOwner->m_nThreadID, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);  
  287.                 if (CommEvent & EV_ERR)//发生线路状态错误,线路状态错误包括CE_FRAME,CE_OVERRUN和CE_RXPARITY   
  288.                     ::PostThreadMessage(port->m_pOwner->m_nThreadID, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);  
  289.                 if (CommEvent & EV_RING)//检测到振铃指示  
  290.                     ::PostThreadMessage(port->m_pOwner->m_nThreadID, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);  
  291.                   
  292.                 if (CommEvent & EV_RXCHAR)  
  293.                     //接收到字符,并置于输入缓冲区中   
  294.                     ReceiveChar(port, comstat);  
  295.                       
  296.                 break;  
  297.             }    
  298.         case 2: // 写事件  
  299.             {  
  300.                 WriteChar(port);  
  301.                 break;  
  302.             }  
  303.         }  
  304.     }  
  305.   
  306.     return 0;  
  307. }  
  308.   
  309. BOOL CSerialPort::StartMonitoring()  
  310. {  
  311.     if (!(m_Thread = AfxBeginThread(CommThread, this)))  
  312.         return FALSE;  
  313.     TRACE("Thread started\n");  
  314.     return TRUE;      
  315. }  
  316.   
  317. //唤醒线程  
  318. BOOL CSerialPort::RestartMonitoring()  
  319. {  
  320.     TRACE("Thread resumed\n");  
  321.     m_Thread->ResumeThread();  
  322.     return TRUE;      
  323. }  
  324.   
  325.   
  326. //线程挂起  
  327. BOOL CSerialPort::StopMonitoring()  
  328. {  
  329.     TRACE("Thread suspended\n");  
  330.     m_Thread->SuspendThread();   
  331.     return TRUE;      
  332. }  
  333.   
  334.   
  335. //查找详细错误信息  
  336. void CSerialPort::ProcessErrorMessage(char* ErrorText)  
  337. {  
  338.     char *Temp = new char[200];  
  339.       
  340.     LPVOID lpMsgBuf;  
  341.   
  342.     FormatMessage(   
  343.         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,  
  344.         NULL,  
  345.         GetLastError(),  
  346.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language  
  347.         (LPTSTR) &lpMsgBuf,  
  348.         0,  
  349.         NULL   
  350.     );  
  351.   
  352.     sprintf(Temp, "WARNING:  %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);   
  353.     MessageBoxA(NULL, Temp, "Application Error", MB_ICONSTOP);  
  354.   
  355.     LocalFree(lpMsgBuf);  
  356.     delete[] Temp;  
  357. }  
  358.   
  359. void CSerialPort::WriteChar(CSerialPort* port)  
  360. {  
  361.     BOOL bWrite = TRUE;  
  362.     BOOL bResult = TRUE;  
  363.   
  364.     DWORD BytesSent = 0;  
  365.   
  366.     ResetEvent(port->m_hWriteEvent);  
  367.   
  368.     // Gain ownership of the critical section  
  369.     EnterCriticalSection(&port->m_csCommunicationSync);  
  370.   
  371.     if (bWrite)  
  372.     {  
  373.         // Initailize variables  
  374.         port->m_ov.Offset = 0;  
  375.         port->m_ov.OffsetHigh = 0;  
  376.   
  377.         // Clear buffer  
  378.         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);  
  379.   
  380.         bResult = WriteFile(port->m_hComm,             
  381.                             port->m_szWriteBuffer,                   // 发送缓冲区首地址  
  382.                             strlen((char*)port->m_szWriteBuffer),    // 消息发送长度  
  383.                             &BytesSent,                             // 实际写入字节数的存储区域指针  
  384.                             &port->m_ov);                  
  385.   
  386.         // deal with any error codes  
  387.         if (!bResult)    
  388.         {  
  389.             DWORD dwError = GetLastError();  
  390.             switch (dwError)  
  391.             {  
  392.                 case ERROR_IO_PENDING:  
  393.                     {  
  394.                         // continue to GetOverlappedResults()  
  395.                         BytesSent = 0;  
  396.                         bWrite = FALSE;  
  397.                         break;  
  398.                     }  
  399.                 default:  
  400.                     {  
  401.                         // all other error codes  
  402.                         port->ProcessErrorMessage("WriteFile()");  
  403.                     }  
  404.             }  
  405.         }   
  406.         else  
  407.         {  
  408.             LeaveCriticalSection(&port->m_csCommunicationSync);  
  409.         }  
  410.     } // end if(bWrite)  
  411.   
  412.     if (!bWrite)  
  413.     {  
  414.         bWrite = TRUE;  
  415.       
  416.         bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port   
  417.                                       &port->m_ov,       // Overlapped structure  
  418.                                       &BytesSent,       // 发送字节数  
  419.                                       TRUE);            // 等待标志  
  420.   
  421.         LeaveCriticalSection(&port->m_csCommunicationSync);  
  422.   
  423.         // deal with the error code   
  424.         if (!bResult)    
  425.         {  
  426.             port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");  
  427.         }     
  428.     }  
  429.   
  430.     //验证是否是期望发送长度  
  431.     if (BytesSent != strlen((char*)port->m_szWriteBuffer))  
  432.     {  
  433.         TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)port->m_szWriteBuffer));  
  434.     }  
  435. }  
  436.   
  437. void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)  
  438. {  
  439.     BOOL  bRead = TRUE;   
  440.     BOOL  bResult = TRUE;  
  441.     DWORD dwError = 0;  
  442.     DWORD BytesRead = 0;  
  443.     unsigned char RXBuff[1024];  
  444.     int nRecvChar = 1;  
  445.   
  446.     memset(RXBuff, 0, 1024);  
  447.     for (;;)   
  448.     {   
  449.         //获得串口权限  
  450.         EnterCriticalSection(&port->m_csCommunicationSync);  
  451.           
  452.         清除串口的通信错误返回当前串口状态  
  453.         bResult = ClearCommError(port->m_hComm, &dwError, &comstat);  
  454.   
  455.         LeaveCriticalSection(&port->m_csCommunicationSync);  
  456.   
  457.         // start forever loop.  I use this type of loop because I  
  458.         // do not know at runtime how many loops this will have to  
  459.         // run. My solution is to start a forever loop and to  
  460.         // break out of it when I have processed all of the  
  461.         // data available.  Be careful with this approach and  
  462.         // be sure your loop will exit.  
  463.         // My reasons for this are not as clear in this sample   
  464.         // as it is in my production code, but I have found this   
  465.         // solutiion to be the most efficient way to do this.  
  466.           
  467.         if (comstat.cbInQue == 0)  
  468.         {     
  469.             //接收缓冲区为空直接退出  
  470.             break;  
  471.         }  
  472.                           
  473.         EnterCriticalSection(&port->m_csCommunicationSync);  
  474.   
  475.         //读缓冲区  
  476.         if (bRead)  
  477.         {  
  478.             bResult = ReadFile(port->m_hComm,        // 串口句柄  
  479.                                &RXBuff,                         // 读缓冲区地址  
  480.                                nRecvChar,                       // 要读取的长度  
  481.                                &BytesRead,                      // 读取长度  
  482.                                &port->m_ov);  
  483.   
  484.             //正常返回值为FALSE,调用GetOverlappedResult获取重叠结果  
  485.             if (!bResult)    
  486.             {   
  487.                 switch (dwError = GetLastError())   
  488.                 {   
  489.                     case ERROR_IO_PENDING:    
  490.                         {   
  491.                             bRead = FALSE;  
  492.                             break;  
  493.                         }  
  494.                     default:  
  495.                         {  
  496.                             port->ProcessErrorMessage("ReadFile()");  
  497.                             break;  
  498.                         }   
  499.                 }  
  500.             }  
  501.             else  
  502.             {  
  503.                 //读取操作完成,不需要调用GetOverlappedResult  
  504.                 bRead = TRUE;  
  505.             }  
  506.         }  
  507.         //获取异步结果  
  508.         if (!bRead)  
  509.         {  
  510.             //重置bRead  
  511.             bRead = TRUE;  
  512.             bResult = GetOverlappedResult(port->m_hComm,  
  513.                                           &port->m_ov,     
  514.                                           &BytesRead,   //返回读取的长度  
  515.                                           TRUE);            // 等待标志  
  516.             if (!bResult)    
  517.             {  
  518.                 port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");  
  519.             }  
  520.         }  
  521.   
  522.         if (bRead)  
  523.         {  
  524.             if (RXBuff[0] == '#')  
  525.             {  
  526.                 nRecvChar = port->m_nDataLen;  
  527.                 continue;  
  528.             }  
  529.             if (strlen((char*)&RXBuff[0]) < port->m_nDataLen)  
  530.             {  
  531.                 nRecvChar = 1;  
  532.                 continue;  
  533.             }  
  534.             std::string *pStrMsg = (port->m_pStringPool)->GetAString();  
  535.             pStrMsg->assign((char *)&RXBuff[0], BytesRead);  
  536.             if (pStrMsg->find('#') != std::string::npos)  
  537.             {  
  538.                 nRecvChar = 1;  
  539.                 (port->m_pStringPool)->ReleaseAString(pStrMsg);  
  540.                 continue;  
  541.             }  
  542.             nRecvChar = 1;  
  543.             //将字符串放入接收队列  
  544.             EnterCriticalSection(&port->m_csQueLock);  
  545.             port->m_strQue.push(pStrMsg);  
  546.             LeaveCriticalSection(&port->m_csQueLock);  
  547.         }  
  548.                   
  549.         LeaveCriticalSection(&port->m_csCommunicationSync);  
  550.           
  551.         ::PostThreadMessage((port->m_pOwner)->m_nThreadID, WM_COMM_RXCHAR, (WPARAM) port, (LPARAM) port->m_nPortNr);  
  552.     }  
  553.   
  554. }  
  555.   
  556. void CSerialPort::WriteToPort(char* string)  
  557. {         
  558.     assert(m_hComm != 0);  
  559.   
  560.     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));  
  561.     strcpy(m_szWriteBuffer, string);  
  562.   
  563.     SetEvent(m_hWriteEvent);  
  564. }  
  565.   
  566. //  
  567. // Return the device control block  
  568. //  
  569. DCB CSerialPort::GetDCB()  
  570. {  
  571.     return m_dcb;  
  572. }  
  573.   
  574. //  
  575. // Return the communication event masks  
  576. //  
  577. DWORD CSerialPort::GetCommEvents()  
  578. {  
  579.     return m_dwCommEvents;  
  580. }  
  581.   
  582. //  
  583. // Return the output buffer size  
  584. //  
  585. DWORD CSerialPort::GetWriteBufferSize()  
  586. {  
  587.     return m_nWriteBufferSize;  
  588. }  
  589.   
  590. std::string *CSerialPort::GetFrontString()  
  591. {  
  592.     EnterCriticalSection(&m_csQueLock);  
  593.     if (!m_strQue.empty())  
  594.     {  
  595.         string *pString = m_strQue.front();  
  596.         m_strQue.pop();  
  597.         LeaveCriticalSection(&m_csQueLock);  
  598.         return pString;  
  599.     }  
  600.     else  
  601.     {  
  602.         LeaveCriticalSection(&m_csQueLock);  
  603.         return NULL;  
  604.     }  
  605. }  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值