转自: http://ticktick.blog.51cto.com
在windows程序设计与开发过程中,特别是涉及到开发嵌入式软硬件系统时,往往会涉及到串口编程。网上以及一些书籍上讲解windows下的串口编程知识也挺多的,但我个人觉得,看完书上的知识点有时依然不知道该如何下手开始自己的程序设计和代码编写,许多知识如果能结合着详细的例子往往能够帮助我们学习得更快,所以,在此,我专门为串口编程初学者设计了一个详细的例子,供大家参考和学习。
下面我将自己用C++编写的串口通信的例子贴出来,其特点如下:
1. 本例子使用了比较规范的软件设计方法,类的设计具有比较好的可扩展性和移植性、代码的注释采用doxgen支持的javaDoc风格。
2. 为了能方便初学者更快地了解和入门,几乎每一行代码都加上了详细的注释,对于注释中如果依然有不清楚的概念,相信你通过百度和google一定能找到答案。
3. 本例子设计的串口操作类可以直接移植到其他的工程中去,大家也可以根据自己的需要添加其他的接口。
4. 本例子只实现了串口数据的基本收发功能,其实为了保证串口数据传输的正确性,往往需要设计一些串口通信协议,协议的设计有待你自己完成,如果以后有时间,我也会尝试提供一种比较基本的串口通信协议设计案例给大家学习。
5. 关于本程序的验证方法,可以使用虚拟串口软件VSPM和串口调试助手进行程序的测试与验证,上述两个软件的使用方法请参考: http://ticktick.blog.51cto.com/823160/285610
下面即为例子工程的三个文件,SerialPort.h、SerialPort.cpp、maincpp
附件中是工程文件,需要使用vs2008打开。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #ifndef SERIALPORT_H_
- #define SERIALPORT_H_
-
- #include <Windows.h>
-
-
-
-
-
-
- class CSerialPort
- {
- public:
- CSerialPort(void);
- ~CSerialPort(void);
-
- public:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- bool InitPort( UINT portNo = 1,UINT baud = CBR_9600,char parity = 'N',UINT databits = 8, UINT stopsbits = 1,DWORD dwCommEvents = EV_RXCHAR);
-
-
-
-
-
-
-
-
-
-
- bool InitPort( UINT portNo ,const LPDCB& plDCB );
-
-
-
-
-
-
-
-
- bool OpenListenThread();
-
-
-
-
-
-
-
-
- bool CloseListenTread();
-
-
-
-
-
-
-
-
-
-
- bool WriteData(unsigned char* pData, unsigned int length);
-
-
-
-
-
-
-
-
- UINT GetBytesInCOM();
-
-
-
-
-
-
-
-
-
- bool ReadChar(char &cRecved);
-
- private:
-
-
-
-
-
-
-
-
-
- bool openPort( UINT portNo );
-
-
-
-
-
-
-
-
- void ClosePort();
-
-
-
-
-
-
-
-
-
- static UINT WINAPI ListenThread(void* pParam);
-
- private:
-
-
- HANDLE m_hComm;
-
-
- static bool s_bExit;
-
-
- volatile HANDLE m_hListenThread;
-
-
- CRITICAL_SECTION m_csCommunicationSync;
-
- };
-
- #endif //SERIALPORT_H_
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include "StdAfx.h"
- #include "SerialPort.h"
- #include <process.h>
- #include <iostream>
-
-
- bool CSerialPort::s_bExit = false;
-
- const UINT SLEEP_TIME_INTERVAL = 5;
-
- CSerialPort::CSerialPort(void)
- : m_hListenThread(INVALID_HANDLE_VALUE)
- {
- m_hComm = INVALID_HANDLE_VALUE;
- m_hListenThread = INVALID_HANDLE_VALUE;
-
- InitializeCriticalSection(&m_csCommunicationSync);
-
- }
-
- CSerialPort::~CSerialPort(void)
- {
- CloseListenTread();
- ClosePort();
- DeleteCriticalSection(&m_csCommunicationSync);
- }
-
- bool CSerialPort::InitPort( UINT portNo ,UINT baud ,char parity ,
- UINT databits , UINT stopsbits ,DWORD dwCommEvents )
- {
-
-
- char szDCBparam[50];
- sprintf_s(szDCBparam, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopsbits);
-
-
- if (!openPort(portNo))
- {
- return false;
- }
-
-
- EnterCriticalSection(&m_csCommunicationSync);
-
-
- BOOL bIsSuccess = TRUE;
-
-
-
-
-
-
-
-
-
-
- COMMTIMEOUTS CommTimeouts;
- CommTimeouts.ReadIntervalTimeout = 0;
- CommTimeouts.ReadTotalTimeoutMultiplier = 0;
- CommTimeouts.ReadTotalTimeoutConstant = 0;
- CommTimeouts.WriteTotalTimeoutMultiplier = 0;
- CommTimeouts.WriteTotalTimeoutConstant = 0;
- if ( bIsSuccess)
- {
- bIsSuccess = SetCommTimeouts(m_hComm, &CommTimeouts);
- }
-
- DCB dcb;
- if ( bIsSuccess )
- {
-
- DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, szDCBparam, -1, NULL, 0);
- wchar_t *pwText = new wchar_t[dwNum] ;
- if (!MultiByteToWideChar (CP_ACP, 0, szDCBparam, -1, pwText, dwNum))
- {
- bIsSuccess = TRUE;
- }
-
-
- bIsSuccess = GetCommState(m_hComm, &dcb) && BuildCommDCB(pwText, &dcb) ;
-
- dcb.fRtsControl = RTS_CONTROL_ENABLE;
-
-
- delete [] pwText;
- }
-
- if ( bIsSuccess )
- {
-
- bIsSuccess = SetCommState(m_hComm, &dcb);
- }
-
-
- PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
-
-
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return bIsSuccess==TRUE;
- }
-
- bool CSerialPort::InitPort( UINT portNo ,const LPDCB& plDCB )
- {
-
- if (!openPort(portNo))
- {
- return false;
- }
-
-
- EnterCriticalSection(&m_csCommunicationSync);
-
-
- if (!SetCommState(m_hComm, plDCB))
- {
- return false;
- }
-
-
- PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
-
-
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return true;
- }
-
- void CSerialPort::ClosePort()
- {
-
- if( m_hComm != INVALID_HANDLE_VALUE )
- {
- CloseHandle( m_hComm );
- m_hComm = INVALID_HANDLE_VALUE;
- }
- }
-
- bool CSerialPort::openPort( UINT portNo )
- {
-
- EnterCriticalSection(&m_csCommunicationSync);
-
-
- char szPort[50];
- sprintf_s(szPort, "COM%d", portNo);
-
-
- m_hComm = CreateFileA(szPort,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- 0,
- 0);
-
-
- if (m_hComm == INVALID_HANDLE_VALUE)
- {
- LeaveCriticalSection(&m_csCommunicationSync);
- return false;
- }
-
-
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return true;
- }
-
- bool CSerialPort::OpenListenThread()
- {
-
- if (m_hListenThread != INVALID_HANDLE_VALUE)
- {
-
- return false;
- }
-
- s_bExit = false;
-
- UINT threadId;
-
- m_hListenThread = (HANDLE)_beginthreadex(NULL, 0, ListenThread, this, 0, &threadId);
- if (!m_hListenThread)
- {
- return false;
- }
-
- if (!SetThreadPriority(m_hListenThread, THREAD_PRIORITY_ABOVE_NORMAL))
- {
- return false;
- }
-
- return true;
- }
-
- bool CSerialPort::CloseListenTread()
- {
- if (m_hListenThread != INVALID_HANDLE_VALUE)
- {
-
- s_bExit = true;
-
-
- Sleep(10);
-
-
- CloseHandle( m_hListenThread );
- m_hListenThread = INVALID_HANDLE_VALUE;
- }
- return true;
- }
-
- UINT CSerialPort::GetBytesInCOM()
- {
- DWORD dwError = 0;
- COMSTAT comstat;
- memset(&comstat, 0, sizeof(COMSTAT));
-
- UINT BytesInQue = 0;
-
- if ( ClearCommError(m_hComm, &dwError, &comstat) )
- {
- BytesInQue = comstat.cbInQue;
- }
-
- return BytesInQue;
- }
-
- UINT WINAPI CSerialPort::ListenThread( void* pParam )
- {
-
- CSerialPort *pSerialPort = reinterpret_cast<CSerialPort*>(pParam);
-
-
- while (!pSerialPort->s_bExit)
- {
- UINT BytesInQue = pSerialPort->GetBytesInCOM();
-
- if ( BytesInQue == 0 )
- {
- Sleep(SLEEP_TIME_INTERVAL);
- continue;
- }
-
-
- char cRecved = 0x00;
- do
- {
- cRecved = 0x00;
- if(pSerialPort->ReadChar(cRecved) == true)
- {
- std::cout << cRecved ;
- continue;
- }
- }while(--BytesInQue);
- }
-
- return 0;
- }
-
- bool CSerialPort::ReadChar( char &cRecved )
- {
- BOOL bResult = TRUE;
- DWORD BytesRead = 0;
- if(m_hComm == INVALID_HANDLE_VALUE)
- {
- return false;
- }
-
-
- EnterCriticalSection(&m_csCommunicationSync);
-
-
- bResult = ReadFile(m_hComm, &cRecved, 1, &BytesRead, NULL);
- if ((!bResult))
- {
-
- DWORD dwError = GetLastError();
-
-
- PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_RXABORT);
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return false;
- }
-
-
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return (BytesRead == 1);
-
- }
-
- bool CSerialPort::WriteData( unsigned char* pData, unsigned int length )
- {
- BOOL bResult = TRUE;
- DWORD BytesToSend = 0;
- if(m_hComm == INVALID_HANDLE_VALUE)
- {
- return false;
- }
-
-
- EnterCriticalSection(&m_csCommunicationSync);
-
-
- bResult = WriteFile(m_hComm, pData, length, &BytesToSend, NULL);
- if (!bResult)
- {
- DWORD dwError = GetLastError();
-
- PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_RXABORT);
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return false;
- }
-
-
- LeaveCriticalSection(&m_csCommunicationSync);
-
- return true;
- }
-
-
-
- #include "stdafx.h"
- #include "SerialPort.h"
- #include <iostream>
-
- int _tmain(int argc, _TCHAR* argv[])
- {
-
- CSerialPort mySerialPort;
-
- if (!mySerialPort.InitPort(2))
- {
- std::cout << "initPort fail !" << std::endl;
- }
- else
- {
- std::cout << "initPort success !" << std::endl;
- }
-
- if (!mySerialPort.OpenListenThread())
- {
- std::cout << "OpenListenThread fail !" << std::endl;
- }
- else
- {
- std::cout << "OpenListenThread success !" << std::endl;
- }
-
- int temp;
- std::cin >> temp;
-
- return 0;
- }