在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;
- }