摘 要:驅動程序是連接操作系統和硬件的橋梁。Windows CE.NET 是面向嵌入式應用的操作系統,它可為有限的硬件資源設計多線程、多任務的操作系統環境。串口是計算機系統的常見接口,在簡單數據傳送方面起重要作用。詳細介紹了串口驅動程序的編寫以及在該驅動下實現與PC的通信。
關鍵詞:多線程;Windows CE .NET;流驅動;串口
中圖分類號:TP311文獻標識碼:A
文章編號:1004-373X(2010)06-109-03
Analysis of Serial Driver and Communication of PC in WinCE.NET
ZHANG Zhengzhu1,2,OUYANG Liubo1
(1.Software School,Hu′nan University,Changsha,410082,China;2.Software College,Fujian University of Technology,Fuzhou,350003,China)
Abstract: Driver program is the bridge to link operating system and hardware.Windows CE.NET is an operating system for embedded application,it designs a multi-thread,multi-task operating system environment for limited resources specially.Serial port is a common computer system interface,has important role in data transmission.The process of how to write the code of serial driver and how to communicate with PC are introduced.
Keywords:multi-thread;Windows CE .Net;stream driver;serial port
0 引 言
Windows CE.NET是Microsoft推出的功能強大的緊湊、高效、可伸縮的32位嵌入式操作系統,主要面對各種各樣的嵌入式系統和產品。該系統所具有的多線程、多任務、完全搶占式的特點是專為各種具有嚴格資源限制的硬件系統所設計的[1]。
Windows CE.NET是可移植的,若將它移植到目標平臺上,則必須為平臺上已建立的設備提供驅動程序。Windows CE.NET自帶大量的硬件驅動程序,其中包括串口。本文以串口驅動為例,闡述如何編寫驅動程序,為操作系統無內置支持的硬件編寫驅動程序提供參考。由于應用程序不是直接與驅動打交道,在此給出實際例子,在串口驅動下實現單片機(SAMSUNG S3C2410)與PC的通信[2],并對該應用程序進行詳細分析。上位機利用串口調試助手V2.1進行結果驗證。
1 Windows CE系統驅動特點
Windows CE.NET的驅動程序可以從多角度進行區分:從加載以及接口方式來分有本機設備驅動程序、可加載驅動(流驅動)程序;從驅動層次上分有獨立驅動程序、層次驅動程序。本機設備的驅動程序用于低級、內置設備;流接口驅動程序實現一組固定的流接口函數,它是一個動態鏈接庫(DLL),由設備管理程序負責加載、管理;單體驅動程序把中斷處理、I/O操作、硬件控制等代碼放在一起。分層驅動程序把驅動程序的代碼分為兩層,即模型設備驅動(Model Device Driver,MMD)和平臺相關驅動(Platform Dependence Driver,PDD)。MDD層包含某一類型的驅動程序所通用的代碼,PDD包含特定硬件或平臺專用的代碼[3]。MDD與PDD之間通過DDSI(Device Driver Service provider Interface)函數進行交互。它們之間的關系如圖1所示。
圖1 單體驅動程序與分層驅動程序
當然這種區分并不是絕對的。串口驅動就是以流驅動接口作為本機設備驅動存在的,同時也是一種分層驅動程序。
2 串口驅動程序分析
串口驅動屬于流驅動。實現流式接口驅動程序通常需要四個步驟[4]:
(1) 為流式接口驅動程序選擇一個前綴;
(2) 實現流式接口驅動DLL所必須的接口函數;
(3) 編寫DLL的導出函數定義文件.DEF;
(4) 為驅動程序配置注冊表。
通常情況下為串口驅動選擇前綴“COM1”;接口函數包括一些以“COM”打頭的函數:COM_Init();COM_Deinit();COM_Open();COM_Close();COM_IOControl();COM_Read();COM_Write();COM_Seek()。這些接口函數屬于MDD層函數。該函數的實現在C:/WINCE420/PLATFORM/SMDK2410/DRIVERS/SERIAL/mdd.c中。
COM_Init是在串口設備被檢測后由設備管理器device.exe調用的,主要的作用是初始化設備。COM_Init先分配一個HW_INDEP_INFO結構體,分配之后再初始化結構體中每個成員,指定驅動程序的優先級,接下來調用函數GetSerialObject(DeviceArrayIndex),這個函數由PDD層定義,返回HWOBJ結構體, MDD通過調用這個函數才能調用底層實現的函數。利用底層函數SerInit設置串口的硬件配置,如波特率,并建立相應的緩沖作為接收的中介(結構體HW_INDEP_INFO和HWOBJ 由微軟提供,路徑為C:/WINCE420/PUBLIC/COMMON/OAK/INC/serhw.h)。
COM_Open在調用CreateFile后,用于以讀/寫模式打開設備,并初始化所需要的空間/資源等,創建相應的實例,為后面的操作做好準備。
COM_Read是獲取串口所接收到數據的操作,COM_Write是把要傳送的數據送到串口。
由于串口驅動屬于流式驅動,以.dll形式存在,所以必須在DEF中定義要導出的接口集。如下建立.def文件:(其中ser2410是驅動程序的名稱)
LIBRARYser2410
EXPORTS
COM_Init
COM_Deinit
COM_Open
COM_Close
COM_Read
COM_Write
COM_Seek
COM_PowerDown
COM_PowerUp
COM_IOControl
為驅動程序配置注冊表是在注冊表中建立驅動程序入口點,以便設備管理器識別和管理。下面是串口驅動在注冊表中的信息(路徑:C:/WINCE420/PLATFORM/SMDK2410/FILES/platform.reg)
\"DeviceArrayIndex\"=dword:0
\"Irq\"=dword:03
\"IoBase\"=dword:50000000
\"IoLen\"=dword:2C
\"Prefix\"=\"COM\"
\"Dll\"=\"SER2410.Dll\"
\"Order\"=dword:0
\"Priority\"=dword:0
\"Port\"=\"COM1:\"
\"DeviceType\"=dword:0
\"FriendlyName\"=\"Serial Cable on COM1:\"
\"Tsp\"=\"Unimodem.dll\"
以上四個步驟完成后,編譯鏈接并把內核下載至目標平臺,此時目標平臺就為串口通信提供了驅動和基礎。
3 串口與PC通信
在工業控制中,常需要將單片機采集到的數據傳送給PC機處理、顯示,并且根據處理結果給單片機發送控制命令。因而它在工業自動化、通信和軍事等領域的應用十分廣泛。隨著Windows CE嵌入式操作系統在工業控制中的廣泛應用,設計和實現Windows CE下PC與單片機的串行通信具有重要的意義[5]。本文在PC機中利用開發工具Embedded Visual C++設計應用程序ComApplacation.exe[6]。該程序能夠將通過串口將目標的數據傳到PC機,并能通過串口讀出從PC機發來的數據并顯示。該應用程序在PC機中編譯、鏈接,形成可執行文件后下載到目標機中,其應用程序界面如圖2所示。
圖2 應用程序界面
上位機利用串口調試助手V2.1[7]接收數據,并發送數據到串口,如圖3所示。
3.1 應用程序編程原理
串口驅動屬于流式驅動。流式接口驅動程序的體系結構如圖4所示[8]。
應用程序使用文件API對設備進行訪問,文件API被操作系統轉發到FileSys.exe進程中;然后FileSys.exe發現是對設備的操作,于是交給設備管理器處理,接著設備管理器根據具體的請求,調用不同的流式接口驅動程序中暴露的接口;最后驅動程序負責與硬件交互。
圖3 串口調試助手界面
圖4 流式接口驅動體
3.2 應用程序代碼分析
由于把設備當作文件來訪問,應用程序的編寫顯得簡單易懂,但需注意以下兩個問題[9]:
(1) 在WinCE.NET中使用的編碼方式都是Unicode,對于串口字符的顯示,存在編碼顯示的問題,即常說的ANSIcode 到Unicode的轉化問題。利用WideCharToMultiByte()和MultiByteToWideChar()進行普通字符(ANSIcode)和寬字符(UNIcode)之間的相互轉化。
(2) 讀/寫串口的速度較主線程慢,讀/寫串口并發執行,所以對讀串口和寫串口應該單獨編寫線程。
代碼主要部分:
打開串口:CreateFile( IndexText,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL );
設置波特率、超時值:
TIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 10;
CommTimeOuts.ReadTotalTimeoutCons tant = 10;
CommTimeOuts.WriteTotalTimeoutMultiplier = 50;
CommTimeOuts.WriteTotalTimeoutConstant = 100;
SetCommTimeouts( hSer,CommTimeOuts );
讀串口:ReadFile(hPort,Byte,1,dwBytes,NULL);
寫串口:WriteFile(hSer,(TCHAR*)WBuf,lstrlen(WriteBuffer)*sizeof(char),dwBytes,NULL)
線程的同步[10]:在Windows CE中采用同步對象方法來協調多線程的執行。一個線程監視一個同步對象,當用信號通知該對象時,解除正在阻塞的線程,并調度該線程。同步對象利用事件方式來實現。
g_hevWriteEnable = CreateEvent(NULL,FALSE,FALSE,NULL);//信號狀態為無信號狀態
SetEvent(g_hevWriteEnable);//設置信號狀態為有信號狀態,這樣才能被
WaitForSingleObject調用
WaitForSingleObject(g_hevReadEnable,INFINITE)//為真,則說明為有信號狀態,程序繼續執行。
3.3 實驗結果
實驗程序采用Embedded Visual C++編寫,在PC機上編譯、調試成功后,下載到運行Windows CE.NET 4.2的實驗板上,實現了與PC機的正確通信,獲得了很好的效果。實驗結果如圖2、圖3所示。當圖2中輸入“hello world”,在圖3調試助手中則立刻顯示“hello world”;在調試助手輸入端輸入“I Can Play!”,則圖2立刻收到該數據并正確顯示。可見該實驗結果是正確的。
4 結 語
在操作系統中設備驅動程序扮演著無名英雄的角色,驅動程序的任務就是把操作系統的驅動接口“映射”到具體的功能實現中。通過驅動程序的抽象,操作系統與應用程序都可以實現,與具體硬件無關,所以驅動的設計與編寫意義重大。為此,詳細分析了基于串口的流驅動程序的編寫,并在該驅動下實現了與PC機的通信,為繼續研究其他硬件驅動和編寫相應的應用程序提供了參考。
參考文獻
[1]姜波.Windows CE.NET程序設計[M].北京:機械工業出版社,2007.
[2]三星S3C2410用戶手冊重點介紹[EB/OL].http://www.pcbon.NET/zuixin_show.asp?id=4360.
[3]周毓林,寧楊,陸貴強,等.Windows CE.NET內核定制及應用開發[M].北京:電子工業出版社,2004.
[4]何宗鍵.Windows CE嵌入式系統[M].北京:北京航空航天大學出版社,2006.
[5]周成朋,徐亞娟,殷小貢.Windows CE.NET4.2下PC與單片機的串行通信[J].現代電子技術,2005,28(8):31-33.
[6]汪兵.EVC高級編程及其應用開發[M].北京:中國水利水電出版社,2005.
[7]串口調試助手2.7[EB/OL].http://dl.pconline.com.cn/html_2/1/75/id=2176pn=0.html.
[8]張冬泉,譚南林,蘇樹強.Windows CE 實用開發技術[M].北京:電子工業出版社,2009.
[9]丁玉芳,石靖峰,李允俊.基于Windows CE.NET 驅動程序設計[J].信息技術,2007,31(4):130-132.
[10]王艷平,張錚.Windows 程序設計[M].北京:人民郵電出版社,2008.