蔣康康,鄭思遠(yuǎn)
(重慶郵電大學(xué)自動(dòng)化學(xué)院 重慶 400065)
USB接口作為一種高速的新型總線接口,支持即插即用設(shè)備,并能為外設(shè)提供電源且易于擴(kuò)展,已成為了計(jì)算機(jī)和嵌入式系統(tǒng)應(yīng)用的主流接口。人機(jī)接口設(shè)備(HID)一直是Windows系統(tǒng)支持較完善的設(shè)備類,不僅提供了完整的USB系統(tǒng)軟件,而且直接提供HID的設(shè)備驅(qū)動(dòng)程序,只要按照HID類的規(guī)范編寫設(shè)備固件程序,就能夠讓W(xué)indows系統(tǒng)自動(dòng)識別設(shè)備,省去了復(fù)雜的驅(qū)動(dòng)程序編寫過程,這樣大大降低了開發(fā)的難度[1]。本文給出了一種利用S3C2440內(nèi)置USB控制器實(shí)現(xiàn)HID類接口的設(shè)計(jì)方案,以及如何在應(yīng)用程序中對HID類設(shè)備進(jìn)行訪問。
S3C2440是基于ARM920T內(nèi)核的一款MCU,主頻高達(dá)400MHz。其內(nèi)部集成的全速USB設(shè)備控制器兼容USB1.1,支持全速和低速兩種運(yùn)行速度,提供了5個(gè)可靈活配置的端點(diǎn),64字節(jié)FIFO存儲(chǔ)器,集成的USB收發(fā)器,支持掛起和遠(yuǎn)程喚醒功能,可方便實(shí)現(xiàn)與計(jì)算機(jī)通信[2]。由于S3C2440內(nèi)部集成了USB控制器,所以接口電路比較簡單,如圖1所示。
圖1 S3C2440的USB接口電路
HID是用于管理和控制大多數(shù)計(jì)算機(jī)的人工輸入設(shè)備,如鍵盤、鼠標(biāo)、游戲桿等;但HID設(shè)備不一定非要是這些人機(jī)交互設(shè)備,只要符合HID設(shè)備級定義規(guī)范要求的都可以認(rèn)為是HID設(shè)備,其具有以下功能特點(diǎn)[3]:①交換數(shù)據(jù)駐留在報(bào)告結(jié)構(gòu)里;②適用于傳輸少量或中量的數(shù)據(jù);③傳輸?shù)臄?shù)據(jù)具有突發(fā)性;④傳輸?shù)淖畲笏俾视邢拗疲虎轃o固定的傳輸率。
USB設(shè)備有4種傳輸方式與主機(jī)進(jìn)行通信:控制方式、中斷方式、批量方式和同步方式。HID類僅支持其中的2種,即控制傳輸和中斷傳輸。HID設(shè)備和主機(jī)上的HID類驅(qū)動(dòng)程序之間是通過缺省的控制管道和中斷管道來傳輸數(shù)據(jù)的,其中控制管道和中斷輸入管道是必須的,中斷輸出管道是可選的[4],如圖2所示。
圖2 HID的數(shù)據(jù)傳輸方式
HID設(shè)備類是在USB的接口描述符中定義的,其除了支持標(biāo)準(zhǔn)USB描述符外,還自行定義了3種描述符,分別為HID描述符(主要用于識別HID設(shè)備所包含的其他類描述符)、報(bào)告描述符(提供HID設(shè)備和主機(jī)問交換數(shù)據(jù)的格式)和物理描述符。一個(gè)HID設(shè)備只能支持一個(gè)HID描述符;可以支持一個(gè)或多個(gè)報(bào)告描述符;物理描述符是可選的,大多數(shù)HID設(shè)備不需要使用它。圖3顯示了HID各種描述符之間的關(guān)系[5]。
圖3 HID各種描述符之間的關(guān)系
USB協(xié)議定義了11種標(biāo)準(zhǔn)請求命令,Get Status,Clear Feature,Set Feature,Set Address,Get Description,Set Description,Get Configuration,Set Configuration,Get Interface,Set Interface和Synch Frame。主機(jī)通過這些請求來獲取設(shè)備的信息及對設(shè)備進(jìn)行設(shè)置。HID類設(shè)備除了支持這些標(biāo)準(zhǔn)請求外,還要實(shí)現(xiàn)以下6種特定請求:Get Report、Set Report、Get Idle、Set Idle、Get Protocol、Set Protocol。Get Report和Set Report的作用是通過控制管道接收和發(fā)送數(shù)據(jù)報(bào)告[6]。
初始化部分是固化程序能暢通運(yùn)行的基礎(chǔ),是USB系統(tǒng)能正常工作的基本工作。主要包括USB設(shè)備控制器中的特殊寄存器初始化、中斷初始化以及描述符的初始化[7]。
USB設(shè)備固件程序的核心就是對主機(jī)請求進(jìn)行響應(yīng),實(shí)現(xiàn)USB設(shè)備枚舉。枚舉是USB設(shè)備插上之后,主機(jī)與設(shè)備最初的數(shù)據(jù)交換過程。在編寫這部分代碼時(shí),首先應(yīng)該清楚USB設(shè)備連接到主機(jī)時(shí),主機(jī)需向USB設(shè)備所發(fā)的所有請求,然后編寫相應(yīng)的代碼來響應(yīng)具體的請求。圖4為USB連接時(shí)總線枚舉的主要過程。
圖4 USB設(shè)備枚舉過程
HID類設(shè)備接收主機(jī)的一系列請求時(shí)都是通過中斷的方式來激活。當(dāng)設(shè)備收到來自USB接口的中斷時(shí),會(huì)立即根據(jù)USB中斷寄存器中的變化來判斷PC的請求,并對其作出相應(yīng)的響應(yīng)。當(dāng)主機(jī)通過缺省的控制通道對USB設(shè)備發(fā)出請求時(shí),設(shè)備的端點(diǎn)0產(chǎn)生中斷,設(shè)備首先從端點(diǎn)0的FIFO中讀出Setup包,然后根據(jù)Setup包中的數(shù)據(jù)來確定具體的響應(yīng)。Setup包內(nèi)的每個(gè)域(或稱字段)值是由主機(jī)負(fù)責(zé)設(shè)置。每個(gè)Setup包由8個(gè)字節(jié)構(gòu)成,可用C語言的結(jié)構(gòu)體數(shù)據(jù)類型描述如下:
USB設(shè)備接收該包的語句為(其中RdPktEp0()為從端點(diǎn)0緩沖區(qū)FIFO中讀取8字節(jié)數(shù)據(jù)的函數(shù),DescSetup為保存Setup包的結(jié)構(gòu)):
RdPktEp0((unsigned char *)&DescSetup,8);
然后根據(jù)Setup包中域bRequest中的值來判斷具體的請求,使用分支語句來實(shí)現(xiàn)不同請求的跳轉(zhuǎn),以完成對主機(jī)標(biāo)準(zhǔn)請求和HID類特定請求的響應(yīng)。形式為:
具體情況如下:
1)當(dāng) bmRequestType=0x80且 bRequest=0x06, 主機(jī)請求類型為GET_DESCRIPTOR,此時(shí)若bValueH為0x01表明主機(jī)向設(shè)備請求設(shè)備描述符;為0x02表明主機(jī)向設(shè)備請求配置描述符;為0x03表明主機(jī)向設(shè)備請求字符串描述符。
2)當(dāng)bmRequestType=0x00且bRequest=0x05,主機(jī)請求類型為SET_ADDRESS,bValueL為設(shè)置的地址值。
3)當(dāng)bmRequestType=0x00且bRequest=0x09,主機(jī)請求類型為SET_CONFIGURATION,bValueL指示了一個(gè)設(shè)置配置。
4)當(dāng)bmRequestType=0x21且bRequest=0x0A,主機(jī)請求類型為Set_Idle,該請求的作用是限制中斷輸入端點(diǎn)的報(bào)告頻率來節(jié)省總線帶寬,bValueH設(shè)置了報(bào)告之間的最大時(shí)間間隔,bValueL設(shè)置了設(shè)備所支持的報(bào)告類型。
5)當(dāng) bmRequestType=0x81,bRequest=0x06且bValueH=0x22,表明主機(jī)向設(shè)備請求報(bào)告描述符。
Windows為應(yīng)用程序訪問HID設(shè)備提供了強(qiáng)大的支持,提供了完整的HID類驅(qū)動(dòng)程序以及相應(yīng)的API函數(shù)。API函數(shù)名中包含Hid字樣的函數(shù)屬于hid.lib,包含Setup字樣的函數(shù)屬于setupapi.lib,使用VC編寫應(yīng)用程序時(shí)需要在工程設(shè)置選項(xiàng)的Link下的Library Modules下加入hid.lib和setupapi.lib,否則會(huì)出現(xiàn)鏈接錯(cuò)誤[8]。
應(yīng)用程序要訪問設(shè)備首先必須利用Windows提供的API函數(shù)枚舉到設(shè)備,圖5為應(yīng)用程序枚舉HID設(shè)備流程。
圖5 應(yīng)用程序枚舉HID設(shè)備流程
枚舉成功后返回設(shè)備句柄,然后就可以調(diào)用ReadFile()和WriteFile()函數(shù)對設(shè)備進(jìn)行讀/寫數(shù)據(jù)了。
圖6 USB HID應(yīng)用程序運(yùn)行界面
根據(jù)上述思路編寫的USB HID主機(jī)應(yīng)用程序的人機(jī)界面如圖6所示。測試時(shí),ARM9控制器S3C2440模塊每隔5ms向PC機(jī)端循環(huán)發(fā)送0~7共八字節(jié)數(shù)據(jù),點(diǎn)擊圖6所示的“接收”,可以看到界面上能準(zhǔn)確無誤顯示收到的數(shù)據(jù)。
該設(shè)計(jì)融合了S3C2440功耗小、代碼執(zhí)行效率高和USB傳輸效率高、結(jié)構(gòu)簡單的優(yōu)點(diǎn), 容易可靠地實(shí)現(xiàn)USB HID設(shè)備的開發(fā),所設(shè)計(jì)程序已經(jīng)在硬件平臺(tái)上成功運(yùn)行。這樣的設(shè)備無需驅(qū)動(dòng),在插入PC后就能立刻開始工作,省去了安裝驅(qū)動(dòng)程序的過程,方便使用。
[1] 馬偉.計(jì)算機(jī)USB系統(tǒng)原理及其主/從機(jī)設(shè)計(jì)[M].北京:北京航空航天大學(xué)出版社,2004.
[2] S3C2440A處理器用戶手冊,Revision 1.
[3] USB Implementer's Forum.Universal Serial Bus Device Class Definition for Human Interface Device 1.11.2001.6.27
[4] 詹克團(tuán),侯國志.USB HID類設(shè)備的開發(fā)[J].電測與儀表,2004,41(5):48-50.
[5] 楊晶晶,江春華.USB HID設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)[J].微計(jì)算機(jī)信息,2006(22):140-143.
[6 劉立,謝劍斌.基于HID類的USB接口技術(shù)研究[J].計(jì)算機(jī)工程與科學(xué),2003,25(5):82-85
[7] 倪陳強(qiáng),陳 贅.基于C8051f340單片機(jī)的USB HID類設(shè)備設(shè)計(jì)[J].現(xiàn)代電子技術(shù),2007,18(257):64-66.
[8] 扶文樹,何 軍,陸信如.USB HID數(shù)據(jù)通信接口的設(shè)計(jì)與實(shí)現(xiàn)[J].工業(yè)控制計(jì)算機(jī),2009,22(2):8-9.