王曉東
(唐山學院 計算機科學與技術系,河北 唐山 063000)
USB總線協議是由Intel,Compaq,Microsoft等七家公司共同制定的串行接口標準[1],協議內部包含完善的主從機通訊機制,支持從高速視頻傳輸到低速查詢傳輸多種通訊模式,傳輸速率高,從USB1.1協議發展到USB3.0協議,速度已達到5.0 Gbps,而且支持設備的帶電熱插拔,因此支持USB總線協議的設備使用起來十分方便,被廣泛應用在通用計算機和邊緣計算領域。如文獻[2]作者使用Windows的DDK開發工具,基于USB總線的HID人機接口協議,開發了一種USB接口自動測試設備。但對于工業系統開發者和廠商來說,USB驅動程序開發過程十分復雜,在Windows環境下需要使用WDK或者DDK開發工具,并且隨著操作系統的升級,開發工具和驅動程序也需要隨之升級,另外,商業開發USB設備驅動還需要繳納認證費用,增加經濟負擔。因此大多數的工業控制器仍然使用串口或者USB轉串口的方式通訊,正常速度為幾十kbps到幾百kbps,效率較低。計算機的USB接口HID(Human Interface Device)類協議[3]負責人機接口設備如鼠標、鍵盤和游戲桿等和計算機交互操作。USB HID接口權限自由度高,特別是鼠標類設備具有操作系統最高權限,其每個操作信號、每組數據都可以在用戶許可的情況下發出或者接收,應用開發用戶可以調用HID接口的API函數支持人機接口類別的設備。
STM32系列硬件是專為要求高性能、低成本、低功耗的嵌入式應用設計的ARM Cortex內核處理器,其內部自帶flash和RAM,接口資源豐富,并自帶USB物理收發器,因此使用單芯片即可構建完整的智能物聯網儀器儀表的核心模塊[4-5]。STM32處理器性價比很高,適合于工業和民用測控領域使用,文獻[6]即使用STM32搭建低成本的測量裝置,實現了高精度的電量測量。STM32處理器的通訊功能強大,在STM32處理器內部集成了USB收發器,支持USB HID通訊協議,使用USB HID接口每次最多可發送1 024個字節,對于USB2.0硬件,最大速度可以達到24.576 MB/s,足以滿足中等性能工業控制器的需求。有學者使用USB HID技術開發了專用的鼠標[7]、鍵盤[8]和手勢輸入設備[9],但是由于沒有主機數據輸出,僅有單向數據輸入功能,不能用于控制器。
本設計基于STM32構建了一個使用USB HID協議的多功能控制器,數據傳輸工作采用中斷傳輸方式,主機和控制器(從機)之間建立相互獨立的寫入和讀出管道,上位機控制軟件直接調用HID接口的API函數實現對下位機硬件的讀寫控制。
基于STM32的USB HID接口控制器的硬件系統結構如圖1所示。控制器選擇STM32F103作為系統主處理器,其工作頻率為72 MHz,采用ARM CortexM3內核,功耗約為0.1 W,其內部集成了兩個AD采樣器,可以直接接收0~3 V的模擬輸入電壓,支持USB全速設備。主處理器通過定時器中斷輸出3.3 V的PWM信號,PWM信號經過光電隔離后輸出給控制驅動電路。本設計使用LED驅動電路進行驗證,由于驅動電路工作在高電壓、大電流狀態下,因此PWM信號必須隔離輸出。在控制器系統集成多路光電隔離的GPIO信號,用于外部開關控制,系統中MAX3232作為UART串口驅動,用于調試接口和功能擴展。

圖1 USB HID接口控制器的硬件系統結構圖
控制器USB HID接口部分的實際電路圖如圖2所示。STM32F103的PA11和PA12分別連接USB總線的DM和DP端,在DP端上拉1.5 kΩ電阻用于全速設備檢測熱插拔事件,如果DP端直接上拉到3.3 V電壓,因從機的上電延遲,會導致枚舉失敗,因此USB總線的上拉電阻接到STM32F103處理器的IO端口PB10,當控制器啟動,在固件main函數中將PB10拉高,從而等待USB插入事件,開始進行枚舉。

圖2 USB HID接口電路圖
參考USB HID協議,USB HID接口控制器和主機之間需建立兩種傳輸管道:控制傳輸管道和中斷傳輸管道。控制傳輸管道用于設備枚舉,從設備上傳設備描述符、配置描述符以及HID描述符等信息,下發Get請求和Set請求,在設備資源方面占用默認的端點0。因為本控制器屬于自定義的HID設備,首先需要重新定義HID報表描述符,在報表描述中增加和修改數據輸入和輸出報告,修改通訊數據包的字長、字數目、傳輸方向、最大值和最小值。HID報表描述符完成后,在HID描述符填充HID報表描述符信息(長度、類別)??刂破魇褂弥袛鄠鬏斶M行實際的負載數據傳輸,其內部分配兩個中斷類型的端點,分別用于數據接收和發送。
控制器USB HID接口主從機枚舉工作和交互過程如圖3所示。主機檢測到從機接入后,開始標準設備枚舉過程,包括請求和接收設備描述符、設置從機地址、請求和接收配置描述符三個步驟。通過標準設備枚舉過程,主機獲得控制器的設備描述符、配置描述符、接口描述符和端點描述符。標準設備枚舉之后,進行HID類設備枚舉,主機向從機發送Get HID類描述符請求,然后收到HID類描述符和報表描述符。在控制器全部枚舉后,系統進入正常的工作狀態,在Windows環境下主機通過調用ReadFile和WriteFile實現和從機之間收發數據。在Linux環境下可以調用libusb庫實現USB HID通訊。HID設備定義了6個HID類請求,在STM32固件程序的Setup階段中斷函數中響應這些請求命令,根據HID請求發送相應的HID類描述符。

圖3 控制器USB HID接口主從機枚舉工作和交互過程
對于自定義的USB總線HID設備,必須重新構建Report報表描述符[3]。圖4是控制器HID協議報表描述符的基本結構,包括輸入報告和輸出報告,有效數據報文包含8個字單元,每個字單元由8個二進制位(1個字節)組成。報表描述符定義好后在HID設備的接口描述符和端點描述符進行傳輸方式定義,接口描述符的bNumEndpoints,bInterfaceClass和bInterfaceProtocol字段分別定義控制器端點數目、HID設備類別以及HID交互協議。

圖4 控制器USB HID接口協議報表描述符的基本結構
控制器STM32硬件的固件程序使用三個數據結構處理USB通訊事務,分別是:①DEVICE_INFO,保存USB請求命令和通訊狀態信息;②DEVICE_PROP,USB通訊過程的回調函數,包括控制傳輸Setup階段處理,Stage IN和OUT事務處理,獲得設備、配置和字符描述符處理;③USER_STANDARD_REQUESTS,一組標準請求回調函數指針,用于定制上位機的標準請求,可編寫相應的函數實例化這些指針,也可以設置成NOP_Process系統函數。本控制器系統函數均設置成NOP_Process。控制器固件程序使用STM32開發庫定義以上三個數據結構的實例化對象指針變量pInformation,pProperty,pUser_Standard_Requests處理USB通訊。在STM32的USB總線的中斷處理USB_LP_CAN1_RX0_IRQHandler中調用CTR_LP中斷服務函數,中斷服務函數內部這三個指針指向結構體對象完成控制傳輸過程。
多功能控制器固件主控程序流程如圖5所示。控制器分別使用中斷模式的端點1(管道EP1)、端點2接收和發送數據。在端點1的中斷服務中如果接收到一串長度和格式符合要求的數據,即作為一條控制消息,將其放入一個消息隊列。在主程序中使用一個while循環任務作為后臺主線程程序,主線程程序首先檢測消息隊列是否為空,如果不為空,則從隊列中讀取一條控制消息,對控制消息進行CRC校驗,如果CRC校驗成功,則將控制消息里命令參數賦值給控制寄存器,然后在后續的過程中根據控制寄存器的值運行PWM控制程序、AD采樣程序、GPIO讀寫程序等子模塊。

圖5 多功能控制器固件主控程序流程圖
針對本USB HID接口多功能控制器,上位機軟件使用API函數實現USB HID功能,在Windows環境下可以調用hid.lib,hidclass.lib,hidparse.lib和setupapi.lib四個接口庫完成,而在Linux環境下可使用libusb調用libusb-1.0.so.0.1.0庫完成。限于篇幅,以下介紹Windows環境下上位機實現USB HID功能編程的方法。
在Windows環境下編程時程序中需要hidsdi.h和setupapi.h兩個頭文件。調用這兩個頭文件必須按照C語言的調用規則。Windows環境下上位機對USB HID接口控制器讀寫流程如圖6所示。首先找到HID設備的GUID,調用后獲得HID設備的指針,然后找到單個HID設備的信息,調用后使用CreaeFile函數按照設備路徑打開,設備打開后讀出設備屬性,然后根據設備屬性找到設備屬性中符合控制器ID(VID和PID)的設備,針對滿足條件的設備重新使用CreateFile函數調用兩次,建立讀寫句柄hReader和hWriter。以上過程是通過調用hidsdi.h和setupapi.h頭文件里面的HidD_GetHidGuid,SetupDiGetClassDevs,SetupDiEnumDeviceInterfaces,SetupDiEnumDeviceInterfaceDetail等一系列API函數實現的。設備檢測過程中,因為USB從機設備最多有127個,因此設備遍歷檢測計數設置為127,即可保證全部HID設備屬性被檢測到。在主機的讀寫進程中直接調用ReadFile和WriteFile函數實現對控制器的讀寫,hReader和hWriter句柄是關鍵參數。

圖6 上位機對USB HID接口控制器讀寫流程圖
在驗證實驗中,USB HID接口控制器和主機之間的數據流管道配置如圖7所示。主機通過EP0端點的控制傳輸方式對控制器進行枚舉和初始化;設備的端點1(管道EP1)用于接收主機實際控制信息,端點2(管道EP2)用于設備數據讀出,EP1,EP2工作采用中斷傳輸方式。控制器數據包的大小采用8個字節,控制器和主機之間采用短數據包的形式保證控制器響應的敏捷性,每個控制輸出事務和狀態讀取的輸入事務均包含8個字節的有效數據。

圖7 控制器和主機之間數據流管道配置
實驗驗證用的處理器型號是STM32F103C8T6。圖8是USB HID接口控制器實際硬件電路和系統測試實驗圖。外部測試硬件使用一個LED光源,通過PWM接口控制LED恒流源驅動器輸出。

(a)實際硬件電路
圖9是示波器顯示的USB HID接口控制器PWM信號輸出的實際波形,其中(a)為50%占空比,(b)為80%占空比,硬件根據控制要求改變PWM信號的占空比。圖10是控制器通過PWM信號控制LED光源獲得的實驗數據,橫坐標為PWM信號的占空比(ratio),其范圍從0.05到1.0(較小數據沒有顯示),縱坐標為LED工作電流值。LED的驅動電路使用LM3409恒流源驅動芯片,在實驗過程中上位機向控制器下發占空比(ratio)和頻率參數,然后控制器根據這兩個參數生成PWM信號,PWM信號控制LED光源驅動芯片輸出的開關,從而調節LED光源的亮度。選擇2 kHz和8 kHz的PWM信號頻率進行測試,由圖10可知,當選擇較高頻率(8 kHz)PWM信號時,LED調節的范圍較大,較小的占空比也有電流輸出,LED電流輸出最小值可以小于1 mA,可見控制器可以很方便地實現一個寬范圍的控制過程。控制器硬件平均工作電流為135 mA,功耗低、性能穩定,數據測試過程中上位機輸出100%成功。系統經過24 h長時間測試,能夠穩定運行。

(a)通道1(50%的占空比)

圖10 控制器通過PWM信號控制LED光源圖示(改變占空比獲得電流輸出)
本文提出了一種基于STM32硬件的USB HID接口多功能控制器設計方案,主機和USB設備之間采用控制管道、讀管道和寫管道等相互獨立的多個傳輸管道實現控制數據的讀寫。通過重新定義USB HID報表描述符和設備與主機之間的雙向通訊控制流程,實現了可編程變頻PWM信號控制、GPIO讀入和輸出、模擬量AD采集多種功能。實驗驗證的結果表明,系統使用靈活,反應快速,可以穩定運行。
此控制器可以在跨平臺操作系統的主機下使用,安裝和部署方便,且免驅安裝,可用于機器視覺系統、生產測試、工業測控自動化、儀器儀表、邊緣計算、可穿戴設備等領域,具備運算處理能力強、功耗小、使用和維護成本低等優點,而且為應對智能傳感器大數據控制的需求,此控制器可以通過增加USB接口設置、修改包長、升級USB協議版本來滿足數據流傳輸的要求,因此具有良好的應用價值。