1.引言
隨著計算機技術、通信技術和數據處理技術的發展,利用計算機實現生成過程的自動化成為了提高生產力、減輕勞動強度的有效手段。其中對周圍環境氣象數據的實時監控不僅與人們的生活息息相關,而且對工業生產中設備的正常運作也起到至關重要的作用。鑒于串行通信是計算機與其他設備進行數據交換時經常使用的方法之一,它具有實現簡單,使用靈活方便,數據傳輸可靠等優點,因此基于串口通信技術,構建一個多線程的氣象監控系統是有十分有必要的。
本文采用串口通信的方式接收由溫度、濕度傳感器采集到當前環境參數,利用Visual C++ 6.0提供的Windows API實現對串口的控制,采用多線程以及雙緩沖隊列技術可以實時獲取采集數據、本地存儲采集處理;同時還利用Socket通信技術使采集數據傳送到遠程監控中心,進行數據分析濾波處理以及數據庫的存儲,并繪制出相應的P—T曲線。
2.軟件系統設計方案
本系統由本地采集計算和遠程監控中心構成一個C/S結構監控系統。在環境惡劣的工業現場,無法進行人為的實時監控,由硬件設備采集環境氣象參數首先發送給本地計算機,然后傳送給遠程監控中心進行處理。本地采集計算機利用Visual C++ 6.0提供的Windows API實現對串口的操作。主要包括串口通信、設備控制、數據存儲等模塊,操作方便,人機界面簡單清晰。在應用過程中,首先需要設定串口配置參數,如波特率、數據位、奇偶校驗等,串口初始化后,程序開始運行,采集到的數據同時被保存在擴展名為.txt文件中。然后通過Socket的通信方式把采集到的數據傳送給遠程監控中心,由它來進行數據在數據庫中的存儲,以及數據平滑濾波處理,并繪制出P—T曲線。整個系統實現流程如圖1所示。
3.程序設計思想
當前,一般的MCU都內置了串口的硬件控制模塊,用戶通過查詢和中斷的方法編寫比較簡單的控制程序就可以使用串口通信。但是,本系統要求在接收數據采集設備發送大量數據的同時完成對己接收到數據的實時存儲,如何處理好二者之間的關系,保證不會造成數據的缺失和程序的崩潰是程序設計的一個難點。本文重點對串口通信程序進行了改進,盡量做到不因為串口通信影響整個系統的性能。
Window的最大特征之一是設備無關性,使得Window程序員不用對硬件直接進行操作。利用Window的SDK提供完備的API函數和以中斷方式驅動的通信程序,可以更加簡化串口通信編程。而且Window系統是搶先式的多任務操作系統,使得應用程序能夠同時執行多個任務,即在一個進程中可以同時運行多個線程,系統可以不停的在多個線程之間切換。所以在串行通訊程序中應用多線程就可以簡化應用程序的結構,把一些復雜的運算放在后臺并行執行,從而大大提高應用程序的響應實時能力。
串口通信程序的輸出與輸入是兩個需要并發執行的操作。如果由主線程獨自完成所有的工作,即在的單線程情況下,程序可能會不定期地鎖定。因此,為了具備實時響應的能力和提高程序的效率,本文的串口通信程序程序設計如圖2所示。
圖2 串口程序設計示意圖
應用程序創建了輸出與輸入兩個子線程共同完成通信任務。而又由于串口發送和接收的數據是相對獨立的,故可將其分開,設置兩個緩沖區,一個是發送緩沖區m_TxQueue,另一個是接收緩沖區m_RxQueue,并為每個緩沖區分別設置兩個指針,一個指向輸出線程將要發送的數據,另一個指向輸入線程將要從緩沖區讀取數據的起始位置。這種方式稱之為采用雙緩沖隊列的方法,保證了無關數據的順序操作。
3.1 多線程的設計
線程是進程內的一條執行路徑.它包含獨立的堆棧和CPU寄存器。每個線程共享所有的進程資源,包括打開的文件、信號標識及動態分配的內存等等。一個進程內的所有線程使用同一個32位地址空間,而這些線程的執行由系統調度程序控制,調度程序決定哪個線程可執行和什么時候執行線程。線程有優先級別,優先權較低的線程必須等到優先權較高的線程執行完仃務后再執行。在VC++6.0中的MFC應用程序的線程是由CwinThread對象來表示,該線程分::用戶界面線程(GUI-Thread)和工作者線程(Worker-Thread)。用戶界面線程能夠提供界面和用戶交互,用于處理用戶輸入和響應各種信息和事件;工作者線程沒有消息循環,主要用來處理應用程序的后臺任務。本文所采用的串口操作線程即為工作者線程。程序通過調用AfxBejinThread()函數自動創建一個CwinThread對象,通過響應己設置好的一組事件句柄來啟動一個線程的執行。
3.1.1 輸出線程
輸出線程比較簡單,它只為串口的寫操作創建一個OVERLAPPED結構,并設置一組事件的句柄。它可響應的事件有刪除線程事件、寫請求事件及中斷請求事件,然后線程進入主循環,等待三個事件之一的發生,以便采取適當的行動。例如當檢測到寫請求事件時,表明輸出緩沖區內有一些數據等待發送,輸出線程便會試圖發送傳送隊列中的所有數據。在寫操作進行時,如果端口比較忙就會進入重疊模式。此時WriteFile( )返回FALSE,用GetLastError( )可以發現當前錯誤是ERROR_ IO_ PENDING,意味著重疊I/O操作已經開始了。若是刪除線程消息到來,輸出線程將跳出循環,關閉事件句柄,最后結束線程。
3.1.2輸入線程
輸入線程較為復雜一些,它既要處理串口數據的讀操作,又要處理串口狀態的讀取。而且由于輸入的數據是隨機到達的,所以輸入線程必須一直讀。輸入線程首先要創建兩個OVERLAPPED結構,用于讀數據和獲得通信事件,并為它們分別創建兩個事件。然后輸入線程要響應四個需要監視的事件:刪除線程事件、讀信息事件、狀態信息事件和讀請求事件設置事件句柄。接著輸入線程便進入主循環,直到刪除線程的消息到來才退出。只要輸入緩沖區有空間可用,輸入線程就會一直讀發送過來的數據。與輸出一樣,如果讀操作失敗了,而且返回的錯誤代碼是ERROR_ IO_ PENDING,意味著還在進行讀的重疊操作。輸入線程在等待數據輸入的同時,也在等待傳入的事件。在輸入線程里可以用SetCommMask( )函數建立事件掩模來監視特定通信資源上的事件。如圖:
圖3 輸入線程示意圖
在應用程序中,輸出線程只是簡單的一直調用WaitForMu1tip1e0bject()等待事件的發生,并以一個Switch Case語句為每個已發生事件提供處理方案。輸入線程的工作繁重許多,它分別調用ReadFile()和WaitCommEvent( )接收數據和通信狀態。如果接收到的是數據,輸入線程將它保存到指定位置。如果是通信狀態,輸入線程將它交給其它函數判斷狀態內容,指引程序下一步的活動。ReadFile()和WaitCommEvent ()都是在重疊模式下工作,其步驟與輸出線程相同。
3.1.3 線程同步
在串口通信程序中,輸入緩沖區和輸出緩沖區能夠被多個線程訪問。它們用于在程序的主線程和輸入、輸出線程之間傳送數據塊。當端口上出現一些操作時,主線程和輸入、輸出線程會經常訪問這兩個對象。如果兩個線程同時處理緩沖區,就會產生不正確的數據,這就破壞了數據的完整性。C++提供了信號量( Semaphore)、互斥對象(Mutex)、臨界區(Critical Section)等手段來保護這些數據對象,防止兩個線程在同一時間訪問同一數據。保持在同一個進程內的線程工作協調一致(線程同步)。其中,臨界區是一種保證在一個時間只有一個線程訪問數據集的非常簡單的方法。當你使用臨界區,你就給了線程一個它們必須共享的對象。任何擁有臨界區對象的線程可以訪問被保護起來的數據,其它線程必須等待直到第一個線程釋放了臨界區對象。此后其它線程可以按照順序搶占臨界區對象,訪問數據。因為線程只有擁有臨界區對象才能訪問數據,而且在一個時刻只有一個線程可以擁有臨界區對象,所以決不會出現一個時刻有多個線程訪問數據的現象。
考慮到本文所設計的通信緩沖區既不允許多個線程同時訪問,又不必供其它進程的線程訪問。因此,臨界區是串口通信程序多線程同步最有效的辦法。
3.2 雙緩沖隊列的設計
為了提高效率,本文把緩沖區數據存儲在標準C++庫中的deque<char>對象中,它作為一種優化的存儲容器支持元素的添加和刪除。它能高效地插入未知數量的對象,并且插入和刪除元素時系統的負擔很小。根據需要,本文創建了兩個獨立的緩沖區對象,一個是發送緩沖區m_TxQueue,另一個是接收緩沖區m_RxQueue,并將它們置于臨界區的保護下,就能確保一次只有一個線程處理緩沖區。本文所設計的類MThreadDeque提供了對緩沖區的各種操作,如Extract(),Clear(),Insert()等,每種操作開始和結束的時候都要調用::EnterCriticalSection( &m_Lock )和::LeaveCriticalSection( &m_Lock ),關鍵代碼如下:
class MThreadDeque
{
protected :
const m_iMaxSize;
deque<char> m_Queue;
CRITICAL_SECTION m_Lock;
public :
MThreadDeque( int max_size ) : m_iMaxSize( max_size )
{
::InitializeCriticalSection( &m_Lock );
}
~ MThreadDeque ()
{
::DeleteCriticalSection( &m_Lock );
}
int Insert( char c )
{
int return_value;
::EnterCriticalSection( &m_Lock );
if ( m_Queue.size() < m_iMaxSize ) {
m_Queue.push_back( c );
return_value = c & 0xff;
} else
return_value = -1;
::LeaveCriticalSection( &m_Lock );
return return_value;
}
……
};
3.3 網絡通信部分的設計
當工業現場環境惡劣,不適合人為操作時,將硬件采集的數據傳送到遠程監控中心進行分析和處理是十分有必要的。Socket套接字是目前最流行的網絡通信應用程序接口之一,利用它可以方便地實現局域網內的數據的傳輸,是開發客戶機/服務器網絡應用程序的重要方法。當向一個套接字寫入時,所送數據會自動出現在套接宇的另一端,另一端可能是相同機器上運行的另一個進程,也可能是世界上任何地方互連的一臺計算機。TCP/IP傳輸層有兩個并列的協議:T C P ( Transport Contro1 Protocol)和UDP(User Datagram Protocol)其中TCP是面向連接的,UDP是無連接的,Socket同時支持這兩種通信模式,所對應的Socket分別為數據流Socket和數據報Socket。數抓流Socket定義了一種可靠的面向連接的服務,實現無差錯、無重復的順序數據傳輸;數據報Socket定義了一個無連接的服務,數據通過相互獨立的包進行傳輸,包的傳輸是無序,并且不保證是否出錯、丟失和重復。本文采用了流式Socket來實現遠程數據傳輸,工作過程如圖4所示。
圖4 Socket通信流程圖
3.4 VC與Sql Sever數據庫的數據交換
VC提供一些接口,可以處理數據庫操作,主要有:開放式數據庫連接(ODBC) ,OLE DB、ActiveXDataObject( ADO )等。ADO基于通用對象組件模型(COM),操作靈活,代碼添加少,本系統采用ADO操作Sql server2000數據庫,主要包括四個基本步驟:
①COM庫的初始化,用#import指令引入ADO庫定義文件;
② 創建Connection對象指針,并用其連接Sql server2000數據庫,本文通過DSN數據源對數據庫進行連接,代碼如下:
m_pConnection->Open("Datasource=adotest;UID=sa;PWD=;","","",adModeUnknown)。
③利用建立好的連接,通過Connection、Command對象執行SQL命令,進行創建表、添加記錄、添加字段等操作,或利用Recordset對象取得結果記錄集進行查詢、處理;
④使用完畢后關閉連接釋放對象。
有了以上基礎,就可以方便的把采集來的數據按照制定的順序存放在Sql Server數據中,可以完成對數據進行快速查詢、瀏覽和刪除等工作。
4.結論
氣象數據能夠進行可靠和實時的采集和通信是本系統實現的的關鍵所在。在系統的實現過程中,遇到許多技術問題,如通信的可靠性、多線程之間的互斥與同步、突發性數據處理與計算機響應速度之間的協調和系統性能問題等,其中有些問題只能在現場調試的過程中發現并加以解決。本系統的實現為氣象監控系統的更進一步發展提供了參考,同時對于實現工業監控系統的集成化、自動化具有極大的推進作用。
參考文獻:
[1]李現勇. Visual C++串口通信技術與工程實踐[M].北京:人民郵電出版社,2002
[2]汪翔,袁輝.Visual C++實踐與提高一網絡編程篇[M].北京:中國鐵道出版社,2001:167-186
[3] 徐軍譯.Visual C++開發人員指南[M],北京:機械工業出版社,1998
[4] 潘愛民.VC++技術內幕(第四版)[M].北京:清華人學出版社,1997.
Remote Weather Date Acquisition System
Based On Multi-thread Serial Communication Technology
YAO lan1,GUI xun2
(1.Department of Control Engineering, ChengDu University of Information Technology Sichuan ,610225,China)
(2.School of Electrical Engineering, Southwest Jiao tong University, Sichuan, 610031,China)
Abstract: The paper introduces one of remote weather data acquisition system which is designed and implemented based on multi-thread serial communication technology. With discussing the key problem and solution of this system at the stage in designing and implementing, the paper gives a elaborate analysis of multi-thread processing technology, serial communication, database accessing technology and Socket communication technology.
Key words: multi-thread, serial communication, database, Socket
姚蘭1,桂勛2
(1.成都信息工程學院控制工程系 成都 610225)
(2.西南交通大學電氣工程學院 成都 610031)