VC++實現串口通信的應用程序設計

 

- 1 -

          VC++實現串口通信的應用程序設計

                   

      摘 要:本文介紹了結合了Win32 的API 函數和C++類的基本思想封裝的一個串行通信類

CSerialPort 類。並通過具體的實例詳細介紹其在VC++6.0 下的實現串口通信方法和過程。

關鍵詞:VC++,串口通信,CSerialPort 類

1. 引言

    在控制領域的研發中,PC 機與外圍控制設備的通訊方式有多種,如串行通信口、並行

通信口、一臺網口(需要網卡支持)、USB 通信口或自制危機接口卡。而串口通信則是在

數據通信速率部是很高的情況下,開發者所採用的最常見、最簡單、最通用的通信方式。並

且考慮到現在的PC 機標準配置都具備兩個串口,因此利用串口資源來開發PC 機與外圍控

制設備之間的通信應該是最方便快捷的[3]。

   在目前常用的各種開發環境(如VB、VC 和Delphi 等)下實現串口通信的方式有很多

種:

   首先,最簡便的方法是採用Microsofe 公司提供的ActiveX 控件實現串口通信,即

MSComm 控件。實現串口通信的編程方法原理上比較簡單,容易實現,但編程的靈活性稍差,

且應用程序運行時必須同時拷入與通信控件相關的文件。

   其次,使用Win32 的API 函數實現串口通信亦是很好的方法。利用 API 函數實現串口

通信的編程方法功能強大 ,靈活性好 ,但原理上比較複雜 ,需要編程人員對串口的硬件工作

原理有較深入的瞭解。

   最後,可以利用VC 運行時庫的標準通信函數實現串口通信。其編程原理簡單,但其使

用性和靈活性較差。

   總之,各種串口通信的實現方式在使用條件、靈活性和複雜程度等方面各有優缺點,分

別適合於各自不同的應用場合。而本文介紹一個結合了Win32 的API 函數和C++類的基本

思想封裝了一個串行通信類CSerialPort 類,通過一個實例介紹,我們發現這個自定義的串

口通信類能夠使得串口通信的實現更加靈活、方便。

2. 串口通信的實現

雖然實現串口通信方法很多,但是一般來說,串行通信程序的工作過程一般分四步[2]:

(1)打開串口:在此步驟中,我們可以實現打開通信資源、設置通信參數、設置通信

事件、創建讀寫事件以及等待串口接收中斷等操作。

(2)讀串口:在此步驟中,當有字符或干擾到達串口時發生EV_ RXCHAR 消息的發

送 ,響應函數接收到此消息後讀取串口接收緩衝區。

(3)寫串口:該步驟是負責將要發送的字符寫入發送串口緩衝區。

(4)關閉串口。

2.1 CSerialPort 通信類的介紹

http://www.paper.edu.cn

- 2 -

2.1.1 CSerialPort 類的定義聲明

class CSerialPort

{

public:

   void ClosePort();

   CSerialPort();

   virtual      ~CSerialPort();

BOOL      InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity =

'            N', UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents =

             EV_RXCHAR, UINT writebuffersize = 1024);

HANDLE       m_hComm;

BOOL          StartMonitoring();

BOOL          RestartMonitoring();

BOOL          StopMonitoring();

DWORD        GetWriteBufferSize();

DWORD        GetCommEvents();

DCB           GetDCB();

void            WriteToPort(char* string);

Void            WriteToPort(char* string,int n);

Void            WriteToPort(LPCTSTR string);

void            WriteToPort(LPCTSTR string,int n);

protected:

void            ProcessErrorMessage(char* ErrorText);

static UINT      CommThread(LPVOID pParam);

static void        ReceiveChar(CSerialPort* port, COMSTAT comstat);

static void        WriteChar(CSerialPort* port);

CWinThread* m_Thread;

CRITICAL_SECTION          m_csCommunicationSync;

BOOL                        m_bThreadAlive;

HANDLE                     m_hWriteEvent;

HANDLE                      m_hShutdownEvent;

HANDLE                      m_hEventArray[3];

OVERLAPPED m_ov;

COMMTIMEOUTS              m_CommTimeouts;

DCB                           m_dcb;

CWnd*                         m_pOwner;

UINT                           m_nPortNr;

char*                            m_szWriteBuffer;

DWORD                        _dwCommEvents;

DWORD                        m_nWriteBufferSize;

};

2.1.2 CSerialPort 類的函數說明

     在構造函數 CSerialPort 中對該類的數據成員進行了初始化。InitPort 函數完成串口的初

始化工作,包括打開串口、設置 SPC 的參數、設置通信事件的時間、建立串口的設備控制

塊。由於串口是一種臨界資源,不允許多個線程或用戶同時訪問,因此在該函數中調用了兩

http://www.paper.edu.cn

- 3 -

個Windows API 函數EnterCriticalSection 和LeaveCriticalSection,以實現對串口的互斥訪問。

   A,串口操作函數:

StartMonitoring 函數調用Windows API 函數:AfxBeginThread 啓動一個SPC 線程,打

開串口。

   RestartMonitoring 函數調用CwinThread 的成員函數:ResumeThread 重啓SPC 線程,

重起串口;

    StopMonitoring 函數調用CwinThread 的成員函數:SuspendThread 停止SPC 線程,關

閉串口。

    B,串口讀寫函數:

    WriteChar 函數調用Windows API 函數:WriteFile 向串口寫數據;

    ReceiveChar 函數調用 Windows API 函數:ReadFile 從串口讀取數據。

    WriteToPort 函數:另外擴充函數,通過不同的變量參數,適應不同的寫串口的需求。

    CommThread 函數是SPC 的線程,完成SPC 的消息循環。該函數調用了WaitCommEvent

函數來等待事件消息,然後進行消息的處理和分發。在消息的處理中調用了WriteChar 函數

和ReceiveChar 函數。另外在這個SPC 線程函數中還進行了必要的異常處理。

    C,其他的相關函數

    其它的幾個函數 ProcessErrorMessage,GetDCB 和GetWriteBufferSize 則完成一些輔助

的功能。

2.2 CSerialPort 串口通信類的具體應用

    前面介紹了CSerialPort 類的聲明以及其中一些重要的函數。下面介紹在VC++6.0 環境

下利用MFC 編寫一個基於對話框的串口通信測試的應用程序[1]。定義實現串口通信的類爲

CSerialPort。

2.2.1 串口初始化

     在我們的例子中,我們在CSerialPort.h 中聲明一個串口類的對象:

     CSerialPort m_SerialPort;

     要實現串口首先需要對串口進行設置和初始化。打開串口後,才能對串口的狀態進行監

控。其串口初始化函數如下:

     InitPort(this, nPort, band, checkbit, databits, stopbits,EV_RXFLAG | EV_RXCHAR,512);

     初始化串口的狀態,每次只能初始化一個串口。其中參數nPort:端口號, band:波特率,

checkbit:校驗位, databits:數據個數, stopbits:停止位均可以通過界面設置,也可以在初始

化串口時直接定義。

     初始化串口完畢後,需要通過StartMonitoring()啓動串口通信線程函數CommThread,

即可立即對所定義的串口進行監聽。

2.2.2 處理函數的定義

     在文件CSerialPort.h 類CSerialPort 的定義中聲明自定義處理函數:

     afx_msg void OnComm(WPARAM ch, LPARAM port);

     在 CSerialPort.cpp 內添加函數OnComm()。實現了對接受到的數據的處理代碼。

     在文件 CSerialPort.cpp 消息映射的BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP

之間添加自定義消息映射宏ON_MESSAGE(WM_COMM_RXCHAR, OnComm),即在接受

http://www.paper.edu.cn

- 4 -

到字節的情況下觸發函數。這樣就可以在串口上存在一個字節的時候就可以觸發OnComm

()函數來處理消息。

2.2.3 寫串口

    在處理完接受的消息的後,就需要將反饋的消息再次寫到串口發送出來,從而完成串口

通信。在這裏我們使用m_SerialPort.WriteToPort(char* string,int n)來完成寫串口,其中定義

了寫到串口的字符串和字符的個數。在CSerialPort 類中,我們補充了其他的WriteToPort 的

函數以滿足其他情況下的需要,在使用的過程中大家可以根據需要選擇合適的寫串口函數,

也可以根據自己的需要來擴充其他的函數。

2.2.4 關閉串口

    在串口通信完畢用m_SerialPort.ClosePort()來關閉串口。

3. 測試

使用“串口調試工具”對編寫的串口測試工具進行調試,用串口線將PC 機上的串口1 和

串口2 相連。將串口調試工具和串口測試工具的參數設置如下所示,其比特率,交驗位,

數據位,停止位設置必須相同,其兩個端口號分別選擇爲端口1,端口2。當兩個端口同時

打開的時候,PC 機上的串口連接線將兩個串口導通。當“串口調試工具”發送“this is a test

program!”信息時,在串口測試工具接受到該條信息。測試結果如下圖所示:圖1:串口調試

器發送信息;圖2:串口測試工具接受信息。

圖 1 串口調試器發送信息

圖 2 串口測試工具接受信息

 

 

 

4. 結束語

    本文應用Win32 的API 函數和C++類的基本思想把對串口的操作封裝成一個串口通信

類的CSeriaPort,採用該串口通信類對串口設備的“屏蔽”,增加對串口操作的透明度,提高

串口傳輸數據的可靠性,方便程序員的編程。另外,還可以根據自己的需求對CSeriaPort

類進行功能擴充。

http://www.paper.edu.cn

 

參考文獻

[1] Kruglinski.《Visual C++ 技術內幕》[M].北京:電子工業出版社,1999.

[2] 李現勇.《Visual C+ +串口通信技術與工程實踐》[M].北京:人民郵電出版社.

[3] 王穎.《用 VC6.0 實現串行通信的三種方法》[J].VC 知識庫在線幫助期,http://www.vckbase.com/,

2000 第9 期:18-20.

Application design of serial communication based on VC++

Wang Zhen, Chen Yongtai

school of information engineering,Wuhan University of Technology, Wuhan, PRC (430070)

Abstract

This paper introduces a new Serial Port class, which is named CSerialPort and is comprised based on

Win32 API and some C++ classes. By introducing one example, we analysis the application of the

CSerialPort class in the serial communication based on VC++.

Keywords:VC++,Serial Communication,Class CSerialPort

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章