焦杰,王英濤
(1.吉林省廣播電視研究所,長(zhǎng)春130041;2.吉林省廣播電視技術(shù)中心臺(tái))
?
用于遠(yuǎn)程廣播監(jiān)測(cè)的組合USB設(shè)備接口設(shè)計(jì)
焦杰1,王英濤2
(1.吉林省廣播電視研究所,長(zhǎng)春130041;2.吉林省廣播電視技術(shù)中心臺(tái))
介紹了一種應(yīng)用在遠(yuǎn)程廣播無(wú)人監(jiān)測(cè)點(diǎn)的組合USB設(shè)備,使用一片STM32F407單片機(jī)的單個(gè)OTG_FS同時(shí)設(shè)計(jì)出兩個(gè)設(shè)備接口,其中一個(gè)是監(jiān)測(cè)專(zhuān)用的自定義USB設(shè)備,另一個(gè)是標(biāo)準(zhǔn)HID設(shè)備。整個(gè)系統(tǒng)除了具備廣播信號(hào)監(jiān)測(cè)接收功能之外,還帶有計(jì)算機(jī)運(yùn)行監(jiān)控看門(mén)狗、遠(yuǎn)程電源遙控器和一個(gè)遠(yuǎn)程USB鍵盤(pán)。對(duì)于64位Windows不允許安裝未簽名的自定義設(shè)備驅(qū)動(dòng)程序問(wèn)題,采取了WinUSB方案解決。
廣播監(jiān)測(cè);USB;組合設(shè)備;WinUSB;STM32F407
在廣播電視監(jiān)管工作中,需要設(shè)置一些遠(yuǎn)程的無(wú)人監(jiān)測(cè)站,用于收測(cè)當(dāng)?shù)氐膹V播無(wú)線(xiàn)電信號(hào),并對(duì)節(jié)目的內(nèi)容進(jìn)行自動(dòng)語(yǔ)音分析,然后利用網(wǎng)絡(luò)把監(jiān)測(cè)信息回傳到監(jiān)測(cè)中心。系統(tǒng)主要由信號(hào)接收監(jiān)測(cè)主機(jī)、監(jiān)測(cè)計(jì)算機(jī)和網(wǎng)絡(luò)設(shè)備組成。為保證系統(tǒng)長(zhǎng)期穩(wěn)定運(yùn)行,還需要具備系統(tǒng)看門(mén)狗、遠(yuǎn)程電源遙控、遠(yuǎn)程HID鍵盤(pán)等附加功能。監(jiān)測(cè)主機(jī)使用一片STM32F407單片機(jī),利用OTG_FS接口設(shè)計(jì)出一種具備信號(hào)監(jiān)測(cè)、系統(tǒng)看門(mén)狗、遠(yuǎn)程鍵盤(pán)等多種功能的組合USB設(shè)備,在實(shí)際應(yīng)用中取得了良好的效果。
為了直截了當(dāng)?shù)亟鉀Q困擾USB相關(guān)研發(fā)過(guò)程中的幾個(gè)實(shí)際問(wèn)題,本文用實(shí)例講述研究過(guò)程中涉及的主要技術(shù)點(diǎn)。
① 如何設(shè)計(jì)多功能的USB組合設(shè)備: 在一片STM32F407的OTG_FS接口上實(shí)現(xiàn)兩個(gè)USB設(shè)備,一個(gè)是自定義的廣播監(jiān)測(cè)接收設(shè)備,另一個(gè)是HID鍵盤(pán)設(shè)備。
② 怎樣解決64位Windows系統(tǒng)的驅(qū)動(dòng)程序: 64位Windows不允許安裝未簽名的驅(qū)動(dòng)程序,限制了自定義USB設(shè)備的應(yīng)用。針對(duì)這一問(wèn)題,本文介紹一種采用WinUSB的解決方案,可以實(shí)現(xiàn)從Windows XP SP2到Windows 10,無(wú)論32位還是64位系統(tǒng)全兼容。
③ 實(shí)現(xiàn)Windows系統(tǒng)中應(yīng)用程序: 設(shè)計(jì)應(yīng)用程序與自定義USB設(shè)備通信、控制設(shè)備,并傳輸大量的廣播節(jié)目聲音數(shù)據(jù)。
④ 系統(tǒng)管理與遠(yuǎn)程HID鍵盤(pán): 利用USB通信實(shí)現(xiàn)系統(tǒng)運(yùn)行看門(mén)狗,并結(jié)合網(wǎng)絡(luò)實(shí)現(xiàn)遠(yuǎn)程電源遙控和遠(yuǎn)程HID鍵盤(pán)功能。
整個(gè)監(jiān)測(cè)前端由信號(hào)接收監(jiān)測(cè)主機(jī)、監(jiān)測(cè)計(jì)算機(jī)和網(wǎng)絡(luò)設(shè)備三大部分組成,其中的信號(hào)接收監(jiān)測(cè)主機(jī)也兼用作遠(yuǎn)程電源遙控器、遠(yuǎn)程USB鍵盤(pán)和系統(tǒng)運(yùn)行看門(mén)狗。遠(yuǎn)程廣播監(jiān)測(cè)前端結(jié)構(gòu)框圖如圖1所示。
圖1 遠(yuǎn)程廣播監(jiān)測(cè)前端結(jié)構(gòu)框圖
信號(hào)接收監(jiān)測(cè)主機(jī)中的接收電路完成廣播信號(hào)的接收,編碼后的聲音數(shù)據(jù)由STM32F407單片機(jī)利用USB接口送給監(jiān)測(cè)計(jì)算機(jī)。監(jiān)測(cè)主機(jī)具有網(wǎng)絡(luò)接口,可以接收監(jiān)測(cè)中心的電源遙控命令,遠(yuǎn)程開(kāi)啟或關(guān)閉計(jì)算機(jī),甚至可以遠(yuǎn)程關(guān)閉網(wǎng)絡(luò)設(shè)備的電源。
監(jiān)測(cè)計(jì)算機(jī)需要定期向單片機(jī)的USB控制接口發(fā)送握手命令,如果單片機(jī)在較長(zhǎng)的時(shí)間內(nèi)不能收到USB握手信息,那么就認(rèn)為監(jiān)測(cè)計(jì)算機(jī)發(fā)生故障,利用電源控制電路關(guān)閉計(jì)算機(jī)電源,過(guò)一段時(shí)間再自動(dòng)打開(kāi),實(shí)現(xiàn)自動(dòng)重啟計(jì)算機(jī)。
單片機(jī)在一個(gè)OTG_FS接口上組合了兩個(gè)USB設(shè)備:一個(gè)具有聲音數(shù)據(jù)接口及控制接口的自定義設(shè)備和一個(gè)HID遠(yuǎn)程鍵盤(pán)。當(dāng)監(jiān)測(cè)計(jì)算機(jī)發(fā)生特殊故障,不能進(jìn)入系統(tǒng)時(shí),利用這個(gè)遠(yuǎn)程鍵盤(pán)可以幫助遠(yuǎn)程排除故障。
單片機(jī)采用USB接口與計(jì)算機(jī)通信的電路非常簡(jiǎn)單,只需把STM32F407的OTG_FS引腳經(jīng)匹配電阻聯(lián)接到計(jì)算機(jī)的USB口即可。單片機(jī)USB接口部分電路圖如圖2所示。
圖2 單片機(jī)USB接口部分電路圖
可以在一個(gè)USB接口上實(shí)現(xiàn)多個(gè)USB設(shè)備,最常見(jiàn)的是那種只有一個(gè)USB插頭的無(wú)線(xiàn)鍵盤(pán)鼠標(biāo)組合。有兩種方法能夠在一個(gè)USB接口上實(shí)現(xiàn)多個(gè)設(shè)備:一種是復(fù)合設(shè)備(Compound Device),另一種是組合設(shè)備(Composite Device)。復(fù)合設(shè)備就是把幾個(gè)獨(dú)立的USB設(shè)備用HUB連接在一起,每個(gè)設(shè)備有各自獨(dú)立的設(shè)備ID。而組合設(shè)備是在一個(gè)設(shè)備上實(shí)現(xiàn)多個(gè)接口,它們共用同一個(gè)設(shè)備ID。復(fù)合設(shè)備中有HUB,具有繼續(xù)向下級(jí)連其他設(shè)備的潛力,但是這種設(shè)計(jì)比較復(fù)雜,占用資源較多。相比之下,如果想要實(shí)現(xiàn)同樣的功能,設(shè)計(jì)組合設(shè)備會(huì)更為簡(jiǎn)單方便。
2.1 實(shí)現(xiàn)USB組合設(shè)備框架
因?yàn)閁SB設(shè)備比較復(fù)雜,所以從零開(kāi)始設(shè)計(jì)絕對(duì)不是個(gè)好主意,利用現(xiàn)成的例子進(jìn)行改造會(huì)方便得多。在STM32F407單片機(jī)固件庫(kù)中,有一個(gè)USB FS Examples USB_Device_Examples HID例子,可以在它的基礎(chǔ)之上修改得到所需要的USB功能。其中有兩個(gè)關(guān)鍵問(wèn)題:需要知道在哪里改和明白應(yīng)該改成什么。
首先需要修改那些描述符,實(shí)現(xiàn)設(shè)備的基本框架。因?yàn)樵O(shè)備描述符部分只需要改PID和VID,比較容易,所以主要的工作內(nèi)容是修改配置描述符、接口描述符和端點(diǎn)描述符。例子程序把這幾個(gè)描述符按順序排列在USBD_HID_CfgDesc數(shù)組中。原來(lái)描述符結(jié)構(gòu)需要修改成新結(jié)構(gòu),如圖3所示。
圖3 描述符結(jié)構(gòu)的修改
2.1.1 修改USB設(shè)備ID
所有PNP設(shè)備都必須具有設(shè)備ID,修改usbd_desc.c中的USBD_VID和USBD_PID,改成不會(huì)與其他設(shè)備沖突的數(shù)值,這兩個(gè)數(shù)值還要寫(xiě)到安裝驅(qū)動(dòng)程序所需的那個(gè)INF文件中。
2.1.2 設(shè)計(jì)通信端點(diǎn)
在usbd_conf.h中添加聲音及其他端點(diǎn)號(hào),并設(shè)定端點(diǎn)包長(zhǎng)度。因?yàn)樵祭邮荋ID鼠標(biāo),所以只有HID_IN_EP一個(gè)IN端點(diǎn)。改成鍵盤(pán)需要增加一個(gè)OUT端點(diǎn)HID_OUT_EP,它可以接收到鍵盤(pán)上指示燈的狀態(tài)信息。為了能傳輸大量的聲音數(shù)據(jù),需要再新加兩個(gè)IN端點(diǎn)VENDOR_IN_EP_AUDIO1和VENDOR_IN_EP_AUDIO2,并多加一個(gè)OUT端點(diǎn)VENDOR_OUT_EP,用于向自定義設(shè)備寫(xiě)出數(shù)據(jù)。因?yàn)殒I盤(pán)的數(shù)據(jù)包比鼠標(biāo)大,所以需要改大HID端點(diǎn)包長(zhǎng)度為64。
2.1.3 配置端點(diǎn)FIFO
使用STM32F407單片機(jī)的OTG_FS進(jìn)行設(shè)計(jì),需要修改usb_conf.h,為各端點(diǎn)重新分配FIFO長(zhǎng)度。必須注意在原始例子默認(rèn)狀態(tài)下,只有EP0和EP1是可用的,其他端點(diǎn)因沒(méi)有分配過(guò)FIFO所以還不能用。需要用哪個(gè)端點(diǎn)就必須給它分配FIFO,特別要注意STM32F407的FIFO總共有320字節(jié),各端點(diǎn)FIFO加起來(lái)的總數(shù)量不可以超過(guò)這個(gè)總長(zhǎng)度。
2.1.4 修改配置描述符
在usbd_hid_core.c設(shè)計(jì)配置描述符,也就是修改USBD_HID_CfgDesc數(shù)組,把bNumInterfaces從1改成2,表示有HID鍵盤(pán)和自定義設(shè)備共計(jì)兩個(gè)接口。再把接口描述符的bNumEndpoints從1改成2,表示這個(gè)HID鍵盤(pán)接口上有兩個(gè)端點(diǎn);nInterfaceProtocol從2改成1表示把鼠標(biāo)改成鍵盤(pán)。
在原來(lái)HID端點(diǎn)描述符之后,仿照原來(lái)的IN端點(diǎn)添加一個(gè)新的HID_OUT_EP端點(diǎn)描述符。注意鍵盤(pán)鼠標(biāo)端點(diǎn)的bmAttributes是3,表示采用中斷傳輸模式。
2.1.5 添加自定義設(shè)備的描述符
在HID端點(diǎn)描述符之后添加自定義設(shè)備的接口描述符,可以復(fù)制前面的HID接口描述符,在其基礎(chǔ)上進(jìn)行修改:
① bInterfaceNumber是順序號(hào),在前面的HID接口描述符里是0,所以輪到這個(gè)需要用1。注意這個(gè)值與后面驅(qū)動(dòng)程序安裝有關(guān),在后面介紹WinUSB驅(qū)動(dòng)程序安裝時(shí)會(huì)再次看到它的作用。
② bNumEndpoints是端點(diǎn)數(shù)量,自定義的監(jiān)測(cè)設(shè)備有3個(gè)端點(diǎn)(bInterfaceClass、bInterfaceSubClass、nInterfaceProtocol),改成0xff、0x00、0x00表示自定義的設(shè)備。在接口描述符后面,依次羅列這三個(gè)端點(diǎn)描述符,仿照HID端點(diǎn)描述符填寫(xiě)即可。
2.1.6 修改HID報(bào)告描述符
HID鍵盤(pán)還需要一個(gè)報(bào)告描述符,因?yàn)檫@個(gè)鍵盤(pán)不需要支持特殊的按鍵和指示燈,所以可以隨便找一個(gè)現(xiàn)成的例子。替換原來(lái)的鼠標(biāo)報(bào)告描述符HID_MOUSE_ReportDesc,并注意修改程序中所有涉及到報(bào)告描述符的長(zhǎng)度數(shù)值。
2.2 實(shí)現(xiàn)USB組合設(shè)備的固件接口程序
把修改數(shù)據(jù)之后形成的組合設(shè)備框架編譯寫(xiě)入STM32F407,接到計(jì)算機(jī)上就可以看到在設(shè)備管理器窗口中會(huì)多出來(lái)三個(gè)設(shè)備:USB Composite Device、HID鍵盤(pán)和沒(méi)有驅(qū)動(dòng)程序的未知設(shè)備。
2.2.1 新添加端點(diǎn)的打開(kāi)與關(guān)閉
在usbd_hid_core.c中添加新端點(diǎn)的打開(kāi)與關(guān)閉消息調(diào)用程序代碼。USBD_HID_Init函數(shù)中,原來(lái)有一個(gè)DCD_EP_Open,它只打開(kāi)了鼠標(biāo)的IN端口。仿照樣子添加打開(kāi)新定義的HID_OUT_EP、VENDOR_OUT_EP、VENDOR_IN_EP_AUDIO1和 VENDOR_IN_EP_AUDIO2端口。在USBD_HID_DeInit函數(shù)中添加DCD_EP_Close,把這幾個(gè)新端口關(guān)閉。
2.2.2 非0端點(diǎn)數(shù)據(jù)收發(fā)
非0端點(diǎn)可以進(jìn)行中斷傳輸或塊傳輸,在usbd_hid_core.c中添加自定義設(shè)備與計(jì)算機(jī)軟件塊傳輸?shù)慕涌诔绦虼a,固件庫(kù)采用函數(shù)回調(diào)的方式來(lái)添加這些功能。在數(shù)據(jù)結(jié)構(gòu)USBD_HID_cb中有一個(gè)DataOut,在那里設(shè)置一個(gè)回調(diào)函數(shù)USBD_VENDOR_DataOut (void *pdev, uint8_t epnum)。當(dāng)計(jì)算機(jī)發(fā)送數(shù)據(jù)到設(shè)備的非0端點(diǎn)時(shí),會(huì)觸發(fā)這個(gè)函數(shù)回調(diào),并傳入?yún)?shù)epnum表明數(shù)據(jù)要發(fā)送到哪個(gè)端點(diǎn),用USBD_GetRxCount庫(kù)函數(shù)可以取得本次單片機(jī)收到的數(shù)據(jù)字節(jié)數(shù)。
在數(shù)據(jù)結(jié)構(gòu)USBD_HID_cb中有一個(gè)SOF和一個(gè)DataIn,在那里設(shè)置兩個(gè)回調(diào)函數(shù),即USBD_VENDOR_SOF(void *pdev)和USBD_VENDOR_DataIn (void *pdev, uint8_t epnum)。USB總線(xiàn)的SOF信號(hào)會(huì)引起周期性地回調(diào)USBD_VENDOR_SOF,可以把這個(gè)函數(shù)回調(diào)作為可以向計(jì)算機(jī)上傳數(shù)據(jù)的啟動(dòng)信號(hào)。每當(dāng)設(shè)備向計(jì)算機(jī)發(fā)完一組數(shù)據(jù)之后,都將回調(diào)USBD_HID_DataIn函數(shù)。因此配合運(yùn)用SOF回調(diào)結(jié)合USBD_HID_DataIn函數(shù),在它們的處理函數(shù)中再使用DCD_EP_Tx庫(kù)函數(shù),可以高速向計(jì)算機(jī)發(fā)送大批量的數(shù)據(jù)。非零端點(diǎn)數(shù)據(jù)發(fā)送中斷回調(diào)與主程序聯(lián)動(dòng)流程圖如圖4所示。
圖4 非零端點(diǎn)數(shù)據(jù)發(fā)送中斷回調(diào)與主程序聯(lián)動(dòng)流程圖
利用“正發(fā)送標(biāo)志”來(lái)協(xié)調(diào)運(yùn)用這兩個(gè)回調(diào)函數(shù),可以快速傳輸大量的聲音數(shù)據(jù)。
2.2.3 專(zhuān)用控制端點(diǎn)0的數(shù)據(jù)收發(fā)
端點(diǎn)0是特殊的控制端點(diǎn),在usbd_req.c中,有一個(gè)USBD_StdDevReq函數(shù),每個(gè)對(duì)設(shè)備EP0的控制傳輸都會(huì)調(diào)用這里。USB_SETUP_REQ 結(jié)構(gòu)保存著從計(jì)算機(jī)發(fā)來(lái)的控制數(shù)據(jù)。對(duì)于查詢(xún)少量數(shù)據(jù)信息的命令,可以直接調(diào)用USBD_CtlSendData庫(kù)函數(shù)傳送一些數(shù)據(jù)應(yīng)答到計(jì)算機(jī)。而對(duì)于執(zhí)行較慢的設(shè)置,有必要聯(lián)合運(yùn)用主程序main函數(shù)設(shè)計(jì)成異步工作方式。圖5是單片機(jī)異步控制、主程序聯(lián)動(dòng)工作流程圖。
圖5 端點(diǎn)0異步控制中斷回調(diào)與主程序聯(lián)動(dòng)流程圖
上位計(jì)算機(jī)把一個(gè)慢速異步設(shè)置分解成“設(shè)置”和“查詢(xún)”兩個(gè)步驟,先通知單片機(jī)進(jìn)行設(shè)置,之后需要定期查詢(xún)?cè)O(shè)置被執(zhí)行的結(jié)果。單片機(jī)收到“設(shè)置”命令之后,緩存設(shè)置參數(shù)退出EP0控制傳輸處理子程序;然后主程序取得緩存的參數(shù)執(zhí)行這個(gè)設(shè)置,把設(shè)置結(jié)論緩存起來(lái)供上位計(jì)算機(jī)進(jìn)行查詢(xún)。整個(gè)“設(shè)置”與“查詢(xún)”兩個(gè)任務(wù)過(guò)程的協(xié)調(diào)核心數(shù)據(jù)是“執(zhí)行狀態(tài)標(biāo)志”變量,0表示空閑沒(méi)有任務(wù);1表示已收到任務(wù)命令但還未執(zhí)行;2表示任務(wù)已開(kāi)始執(zhí)行;3表示任務(wù)已經(jīng)執(zhí)行完畢可查詢(xún)到執(zhí)行結(jié)果。
2.2.4 HID鍵盤(pán)收發(fā)數(shù)據(jù)
前面在定義端點(diǎn)時(shí),HID鍵盤(pán)使用兩個(gè)中斷類(lèi)型端點(diǎn)HID_IN_EP和HID_OUT_EP收發(fā)數(shù)據(jù)。利用HID_IN_EP端點(diǎn),可以把從網(wǎng)絡(luò)遠(yuǎn)程傳來(lái)的數(shù)據(jù)轉(zhuǎn)成鍵盤(pán)按鍵信息。
一條按鍵信息有8個(gè)字節(jié):
第一字節(jié)為SHIFT、CTRL等特殊控制鍵的位組合,每位代表一個(gè)按鍵;
第二字節(jié)為保留字節(jié);
后面字節(jié)為每一個(gè)字節(jié)都可以填入鍵盤(pán)掃描碼,支持6個(gè)鍵同時(shí)按下。
主程序可以調(diào)用DCD_EP_Tx庫(kù)函數(shù)向計(jì)算機(jī)發(fā)送鍵盤(pán)信息,一次鍵盤(pán)信息由一個(gè)按鍵通碼和一個(gè)斷碼組成。用于系統(tǒng)維護(hù)的遠(yuǎn)程鍵盤(pán)不需要支持同時(shí)多按鍵功能,也不需要特殊控制鍵。如果想要按一下回車(chē)鍵,那么發(fā)送通碼數(shù)據(jù)是{0,0,0x28,0,0,0,0,0},斷碼是8個(gè)0。
在Windows系統(tǒng)中,組合USB設(shè)備的這個(gè)HID鍵盤(pán)不需要額外的驅(qū)動(dòng)程序,而自定義的USB設(shè)備必須安裝驅(qū)動(dòng)程序。64位系統(tǒng)對(duì)驅(qū)動(dòng)程序的要求較為嚴(yán)格,只有經(jīng)過(guò)數(shù)字簽名的驅(qū)動(dòng)程序才可以正常安裝。本文介紹使用系統(tǒng)自帶的WinUSB驅(qū)動(dòng)程序可以滿(mǎn)足自定義USB設(shè)備的需要。
3.1 WinUSB簡(jiǎn)介
WinUSB是Windows系統(tǒng)自帶的USB驅(qū)動(dòng)程序,用它可以讓自定義的USB設(shè)備在XP、Vista、Win7、Win8、Win10上得到全面的支持,不論是32位還是64位,都能兼容。驅(qū)動(dòng)開(kāi)發(fā)工作僅僅是再提供一個(gè)INF文件去安裝自定義的USB設(shè)備。
3.2 WinUSB驅(qū)動(dòng)程序安裝
在MSDN,有一篇名為《WinUSB (Winusb.sys) 安裝》[3]的文章,里面可以找到安裝過(guò)程的介紹。除非有特殊的問(wèn)題要查找,否則不需要細(xì)看那些內(nèi)容,直接從“編寫(xiě)適用于WinUSB安裝的自定義INF”那段復(fù)制INF例子內(nèi)容,在其基礎(chǔ)上修改成自己的安裝程序。
對(duì)于普通的USB設(shè)備,只需找到%DeviceName% =USB_Install, USBVID_0547&PID_1002那行,改成前面在usbd_desc.c中的USBD_VID和USBD_PID就可以了。然而對(duì)于本文介紹的這種組合USB設(shè)備,還需要在PID的后面增加接口序號(hào)。在前面介紹接口描述符時(shí),自定義設(shè)備的接口號(hào)是1,所以設(shè)備名要寫(xiě)成:USBVID_0547&PID_1002&MI_01。
INF文件中還有一節(jié):
[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{9f543223-cede-4fa3-b376-a25ce9a30e74}"
需要注意這行與應(yīng)用程序枚舉驅(qū)動(dòng)程序有關(guān),這個(gè)GUID在本文后面設(shè)計(jì)應(yīng)用程序時(shí)會(huì)用到。
應(yīng)用程序必須調(diào)用Winusb.dll與自定義的USB設(shè)備通信,其接口說(shuō)明在參考文獻(xiàn)[4]中有介紹,應(yīng)用程序接口設(shè)計(jì)在參考文獻(xiàn)[5]中有較詳細(xì)的介紹,并提供了代碼。這里不重復(fù)介紹其內(nèi)容,只對(duì)容易出現(xiàn)的問(wèn)題提供解決方法。
4.1 準(zhǔn)備Winusb.dll的接口H文件
為了讓?xiě)?yīng)用程序代碼適用于多種編譯環(huán)境,建議采用動(dòng)態(tài)加載Winusb.dll的方法來(lái)控制自定義的USB設(shè)備。對(duì)應(yīng)的接口H文件Winusb.h可以在WDK中找到。
4.2 枚舉自定義的組合USB設(shè)備
在MSDN中介紹了用SetupDiGetClassDevs和SetupDiEnumDeviceInterfaces這兩個(gè)API來(lái)枚舉USB設(shè)備,需要注意輸入的GUID參數(shù)。本文在前面介紹INF文件提到過(guò)這行:
圖6 用控制線(xiàn)程強(qiáng)制退出數(shù)據(jù)讀阻塞的流程
HKR,,DeviceInterfaceGUIDs,0x10000,"{9f543223-cede-4fa3-b376-a25ce9a30e74}"
必須用這里的GUID進(jìn)行枚舉,才能正確找到這個(gè)自定義設(shè)備。在枚舉成功之后,用Setup DiGet Device Interface Detail取得設(shè)備驅(qū)動(dòng)的設(shè)備路徑實(shí)例,應(yīng)用程序可以利用WM_DEVICECHANGE消息,在處理函數(shù)中枚舉設(shè)備在線(xiàn)情況,可以對(duì)USB的熱插拔進(jìn)行及時(shí)處理。
4.3 打開(kāi)與關(guān)閉設(shè)備驅(qū)動(dòng)
用API函數(shù)CreateFile打開(kāi)設(shè)備,可以得到自定義設(shè)備的文件句柄。為了使用WinUSB,要求這個(gè)API的參數(shù)必須設(shè)置FILE_FLAG_OVERLAPPED標(biāo)志。
在WinUSB.dll中,所有函數(shù)都用WinUsb_開(kāi)頭。WinUsb_Initialize利用設(shè)備的文件句柄創(chuàng)建一個(gè)WinUSB接口句柄,如果出錯(cuò),很可能是枚舉時(shí)用錯(cuò)了GUID。成功創(chuàng)建之后就可以調(diào)用WinUSB的其他函數(shù)與單片機(jī)通信了。在程序退出或設(shè)備撤出時(shí),必須調(diào)用CloseHandle關(guān)閉設(shè)備,用WinUsb_Free關(guān)閉WinUSB接口句柄。
4.4 控制端點(diǎn)EP0通信
本文在前面介紹單片機(jī)的控制端點(diǎn)EP0時(shí),提到過(guò)USB_SETUP_REQ 結(jié)構(gòu)。在WinUsb中有一個(gè)對(duì)應(yīng)的WINUSB_SETUP_PACKET數(shù)據(jù)結(jié)構(gòu),它們是同樣的數(shù)據(jù)結(jié)構(gòu)。也就是說(shuō),應(yīng)用程序調(diào)用WinUsb_ControlTransfer時(shí),會(huì)把WINUSB_SETUP_PACKET參數(shù)原樣送給單片機(jī),然后單片機(jī)用USBD_CtlSendData庫(kù)函數(shù)應(yīng)答的數(shù)據(jù)會(huì)填充到WinUsb_ControlTransfer的Buffer參數(shù)里返回給應(yīng)用程序。
4.5 非0端點(diǎn)塊傳輸通信
應(yīng)用程序調(diào)用WinUsb_WritePipe向單片機(jī)寫(xiě)入塊數(shù)據(jù),會(huì)觸發(fā)單片機(jī)中USBD_HID_cb結(jié)構(gòu)上那個(gè)DataOut函數(shù)回調(diào)接收數(shù)據(jù)。單片機(jī)用DCD_EP_Tx庫(kù)函數(shù)發(fā)出的數(shù)據(jù)可以在應(yīng)用程序中調(diào)用WinUsb_ReadPipe讀取。
通常為簡(jiǎn)化程序設(shè)計(jì),所以設(shè)置WinUsb_WritePipe和WinUsb_ReadPipe的Overlapped參數(shù)為NULL。在此情況下,這兩個(gè)函數(shù)都是阻塞的,如果出現(xiàn)某種情況,單片機(jī)不能提供足夠的數(shù)據(jù)供計(jì)算機(jī)讀取,或者不能接收計(jì)算機(jī)發(fā)出的數(shù)據(jù),都會(huì)導(dǎo)致計(jì)算機(jī)程序鎖死在那里,不能繼續(xù)向下執(zhí)行。圖6描述了一個(gè)在數(shù)據(jù)讀取阻塞時(shí),利用控制線(xiàn)程強(qiáng)制退出阻塞狀態(tài)的流程。因此有必要利用多任務(wù)把數(shù)據(jù)管道讀或?qū)懙墓δ塥?dú)立到另一個(gè)線(xiàn)程中,主程序線(xiàn)程利用控制端點(diǎn)EP0來(lái)控制單片機(jī)那里對(duì)數(shù)據(jù)的接收和發(fā)送,在特殊情況下可以通知單片機(jī)強(qiáng)制接收并丟棄數(shù)據(jù),或者胡亂發(fā)送一些填充數(shù)據(jù),這樣就可以跳出WinUsb_WritePipe和WinUsb_ReadPipe的阻塞狀態(tài)。
對(duì)整個(gè)監(jiān)測(cè)系統(tǒng)的管理就是看門(mén)狗與遠(yuǎn)程遙控管理,遠(yuǎn)程控制功能有計(jì)算機(jī)遠(yuǎn)程遙控軟件和網(wǎng)絡(luò)遠(yuǎn)程遙控硬件兩個(gè)組成部分。
5.1 遠(yuǎn)程電源管理器
計(jì)算機(jī)系統(tǒng)運(yùn)行正常是所有計(jì)算機(jī)遠(yuǎn)程遙控軟件可以正常使用的根本前提。一旦Windows系統(tǒng)死機(jī)或者進(jìn)不去了,那么再優(yōu)秀的遙控軟件也都無(wú)計(jì)可施。在這種情況下,解決的辦法就只剩下計(jì)算機(jī)斷電重啟了。
使用STM32F407固件庫(kù)中的LwIP設(shè)計(jì)一個(gè)網(wǎng)絡(luò)WEB服務(wù)器程序,實(shí)現(xiàn)遠(yuǎn)程在頁(yè)面上遙控單片機(jī)的一個(gè)I/O口電平,只需將這個(gè)I/O口連接到一個(gè)由三極管控制的繼電器上,就能實(shí)現(xiàn)對(duì)計(jì)算機(jī)電源的遙控功能。
用類(lèi)似的方法可以設(shè)計(jì)網(wǎng)絡(luò)設(shè)備的遠(yuǎn)程遙控電路。然而當(dāng)網(wǎng)絡(luò)設(shè)備斷電之后,整個(gè)前端就無(wú)法再繼續(xù)遙控了,因此單片機(jī)對(duì)網(wǎng)絡(luò)的控制邏輯是斷電后延時(shí)幾分鐘再自動(dòng)加電。
5.2 計(jì)算機(jī)系統(tǒng)運(yùn)行看門(mén)狗
系統(tǒng)中有兩大看門(mén)狗,一個(gè)是計(jì)算機(jī)運(yùn)行看門(mén)狗,另一個(gè)是網(wǎng)絡(luò)運(yùn)行看門(mén)狗。計(jì)算機(jī)必須定期通過(guò)USB向單片機(jī)的VENDOR_OUT_EP端點(diǎn)發(fā)出喂狗命令,否則單片機(jī)就會(huì)認(rèn)為計(jì)算機(jī)發(fā)生故障而自動(dòng)關(guān)閉計(jì)算機(jī)電源,過(guò)幾分鐘自動(dòng)通電再讓它重啟動(dòng)。
在單片機(jī)中記錄著監(jiān)測(cè)中心服務(wù)器的IP地址,并且會(huì)定期主動(dòng)聯(lián)接服務(wù)器的一個(gè)特定TCP端口。一旦單片機(jī)長(zhǎng)時(shí)間始終無(wú)法與服務(wù)器聯(lián)接,就認(rèn)為網(wǎng)絡(luò)設(shè)備發(fā)生故障,將自動(dòng)對(duì)網(wǎng)絡(luò)設(shè)備斷電,然后延遲一段時(shí)間再上電,實(shí)現(xiàn)網(wǎng)絡(luò)設(shè)備遇到故障時(shí)的復(fù)位重新啟動(dòng)。
5.3 遠(yuǎn)程HID鍵盤(pán)
有時(shí)計(jì)算機(jī)會(huì)卡在系統(tǒng)啟動(dòng)期間,需要現(xiàn)場(chǎng)操作鍵盤(pán)解決。例如64位WIN7有時(shí)發(fā)生故障會(huì)卡在“系統(tǒng)修復(fù)”界面,在這種情況下,如果沒(méi)人去按一下鍵盤(pán)回車(chē)鍵,那么就不能繼續(xù)啟動(dòng)運(yùn)行。這種系統(tǒng)故障發(fā)生時(shí),因?yàn)橄到y(tǒng)沒(méi)起來(lái),遠(yuǎn)程軟件還沒(méi)啟動(dòng),所以任何軟件辦法都失靈,只有
依靠設(shè)計(jì)在組合USB設(shè)備中的HID鍵盤(pán)來(lái)執(zhí)行遠(yuǎn)程系統(tǒng)修復(fù)了。在監(jiān)測(cè)中心利用網(wǎng)絡(luò)遠(yuǎn)程登陸單片機(jī)的WEB服務(wù)器,在頁(yè)面上點(diǎn)擊“發(fā)送回車(chē)鍵”按鈕,單片機(jī)就可以把一個(gè)回車(chē)按鍵信息的一個(gè)通碼附加上一個(gè)斷碼從USB輸入計(jì)算機(jī),就像在那個(gè)監(jiān)測(cè)點(diǎn)現(xiàn)場(chǎng)直接鍵入回車(chē)信息一樣。有了這樣一種遠(yuǎn)程鍵盤(pán),即使遠(yuǎn)程無(wú)人前端進(jìn)入不了系統(tǒng),或者沒(méi)有遠(yuǎn)程遙控軟件,也可維護(hù)計(jì)算機(jī)了。
[1] 張秀娟,梁波.多功能USB組合設(shè)備的結(jié)構(gòu)設(shè)計(jì)[J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2011(11).
[2] Microsoft提供的USB驅(qū)動(dòng)程序[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff538853(v=vs.85).aspx.
[3] WinUSB (Winusb.sys)安裝[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff540283.
[4] WinUSB Functions[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff540046 (v=vs.85). aspx#winusb.
[5] 編寫(xiě)基于WinUSB模板的Windows 桌面應(yīng)用[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/dn376872(v=vs.85).aspx.
[6] STMicroelectronics.STM32F405xx/07xx advanced ARM-based 32-bit MCUs Reference manual,2013.
焦杰(工程師),主要研究方向?yàn)閺V播電視信號(hào)監(jiān)測(cè)與控制技術(shù);王英濤(高級(jí)工程師),主要從事調(diào)頻廣播和無(wú)線(xiàn)電視信號(hào)播出工作。
(責(zé)任編輯:楊迪娜 收修改稿日期:2016-09-30)
Design of USB Composite Device Interface for Remote Broadcast Monitoring
Jiao Jie1,Wang Yingtao2
(1.Radio&Television Research Institute of Jilin Province,Changchun 130041,China;2.Radio&Television Technology Center Station of Jilin Province)
In the paper,a USB composite device for broadcasting remote monitoring based on a STM32F407 microcontroller is introduced.Two device interfaces are designed by one OTG_FS circuit interface.The one is the custom USB device,the other one is the standard HID device.In addition to the radio signal receiving and monitoring,some other functions are designed,such as a power controller and a USB keyboard both from the remote network,and a watchdog of computer system is designed.For 64-bit Windows does not allow the installation of the unsigned custom device driver issues,the paper introduces WinUSB to solve it.
broadcasting monitoring;USB;composite device;WinUSB;STM32F407
TP37
A