亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        WinUSB驅(qū)動(dòng)實(shí)現(xiàn)及其通信傳輸應(yīng)用

        2018-09-14 07:51:18石保敬王長(zhǎng)荀怯肇乾
        軟件 2018年8期
        關(guān)鍵詞:句柄描述符線程

        石保敬,王長(zhǎng)荀,怯肇乾

        ?

        WinUSB驅(qū)動(dòng)實(shí)現(xiàn)及其通信傳輸應(yīng)用

        石保敬,王長(zhǎng)荀,怯肇乾

        (河南馳誠(chéng)電氣,河南 鄭州 450001)

        微軟近年來推出的規(guī)范簡(jiǎn)便的WinUSB設(shè)備通信模型,編程對(duì)接的關(guān)鍵是“底層USB設(shè)備如何添加描述使Windows OS識(shí)別其為WinUSB設(shè)備”和“可視化測(cè)試/應(yīng)用程序怎樣通過WinUSB.dll調(diào)用與之進(jìn)行管道數(shù)據(jù)傳輸?shù)膶?shí)現(xiàn)”,恰到好處的運(yùn)用定時(shí)器或線程是異步快速實(shí)時(shí)數(shù)據(jù)接收軟件設(shè)計(jì)的核心,USB測(cè)試/應(yīng)用程序發(fā)布針對(duì)低級(jí)操作系統(tǒng)版本需要編寫引導(dǎo)安裝程序,USB設(shè)備插拔處置和多USB設(shè)備通信的操控也需要特定處置,如此編程設(shè)計(jì),Windows下USB設(shè)備傳輸通信就如同傳統(tǒng)的RS-232C通信一樣方便自如而且還直截了當(dāng)和迅速高效了。

        USB描述符;WinUSB設(shè)備;異步數(shù)據(jù)傳輸;定時(shí)數(shù)據(jù)接收;線程數(shù)據(jù)接收

        0 引言[9]

        Windows操作系統(tǒng)OS(Operation System)下,通過USB(Universal Serial Bus)接口,讀寫訪問USB設(shè)備,是嵌入式應(yīng)用系統(tǒng)和可視化測(cè)試/應(yīng)用軟件開發(fā)必不可少的常用環(huán)節(jié)。微軟從Winxp-SP2版本開始,在Windows中集成了通用的WinUSB Device驅(qū)動(dòng)及其連接OS底層和應(yīng)用層的WinUSB.dll,極大簡(jiǎn)化了USB數(shù)據(jù)的通信傳輸。恰到好處的運(yùn)用WinUSB進(jìn)行開發(fā),同樣可以到達(dá)類似使用傻瓜托管式的WinDriver軟件的效果。編程設(shè)計(jì)的關(guān)鍵是如何讓W(xué)indows快速的把USB設(shè)備識(shí)別為通用WinUSB設(shè)備和應(yīng)用軟件怎樣合理調(diào)用WinUSB.dll對(duì)應(yīng)的WinUSB.lib庫。本文就此展開詳細(xì)闡述。

        開發(fā)WinUSB驅(qū)動(dòng)實(shí)現(xiàn)及其通信傳輸應(yīng)用,可以采用C++、C#或JavaScript等語言,最好的集成開發(fā)環(huán)境IDE(Integrated Development Environment)是Visial Studio,也可以是Rad Studio XE等,無論哪個(gè)IDE都需要首先安裝Windows驅(qū)動(dòng)程序開發(fā)工具包WDK(Windows Driver Kit)。這里以Rad Studio XE和STM32F103系列微控制器的可視化USB設(shè)備通信開發(fā)為例加以說明。

        1 底層USB設(shè)備通信支持[1-4]

        嵌入式應(yīng)用系統(tǒng)實(shí)現(xiàn)USB設(shè)備通信,主要是在高優(yōu)先級(jí)的中斷服務(wù)程序中實(shí)現(xiàn)的,包括常規(guī)的USB標(biāo)準(zhǔn)請(qǐng)求應(yīng)答和管道讀寫收發(fā)實(shí)現(xiàn),管道操作主要是中斷和批量傳輸,USB標(biāo)準(zhǔn)請(qǐng)求包括設(shè)備、配置、接口及其端點(diǎn)描述與速度限定變換。必須設(shè)法讓W(xué)indows識(shí)別為通用WinUSB設(shè)備,可視化測(cè)試/應(yīng)用程序才可以使用通用的WinUSB設(shè)備驅(qū)動(dòng)進(jìn)行溝通交互,如圖1所示。

        圖1 通用WinUSB設(shè)備的操作系統(tǒng)識(shí)別

        為此,需要特別構(gòu)造1個(gè)標(biāo)準(zhǔn)USB類描述符--OS描述符和2個(gè)供應(yīng)商類描述符--OS特征ID(Identifier)描述符和注冊(cè)設(shè)備接口GUID描述符。全球唯一標(biāo)識(shí)符GUID(Globally Unique Identifier)。

        1.1 標(biāo)準(zhǔn)USB類OS描述符

        OS描述符,定義存儲(chǔ)在字符串索引0xEE 處,對(duì)應(yīng)的USB標(biāo)準(zhǔn)請(qǐng)求為:

        80 06 ee 03 00 00 12 00

        典型的OS描述符定義如下:

        #define bMS_VendorCode 0x01

        //Vendor 請(qǐng)求的請(qǐng)求代碼

        const unsigned char OsDscrptStr[] =

        // "MSFT100" : index : 0xEE : langId : 0

        { 0x12, 0x03, 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, bMS_VendorCode, 0 };

        1.2 供應(yīng)商類OS特征ID描述符

        供應(yīng)商類OS特征ID描述符,用作設(shè)置擴(kuò)展兼容,對(duì)應(yīng)的供應(yīng)商類請(qǐng)求為:

        初步請(qǐng)求--c0 01 00 00 04 00 10 00,再次請(qǐng)求--c0 01 00 00 04 00 28 00

        典型的OS特征ID描述符包定義如下:

        const unsigned char cptbIdDscrpt [] =

        { 0x28, 0x00, 0x00, 0x00, //包長(zhǎng)

        0x00, 0x01, //BCD版本

        0x04, 0x00, //索引

        0x01, //數(shù)量

        0x00, 0x00, 0x00, 0x00,

        0x00, 0x00, 0x00, //保留[7]

        0x00, //第一接口編號(hào)

        0x01, //保留(0x01)

        'W', 'I', 'N', 'U', 'S', 'B',

        0x00, 0x00, //兼容ID[8]

        0x00, 0x00, 0x00, 0x00,

        0x00, 0x00, 0x00, 0x00, //子兼容ID[8]

        0x00, 0x00, 0x00,

        0x00, 0x00, 0x00 //保留[6]

        };

        1.3 供應(yīng)商類注冊(cè)設(shè)備接口GUID

        供應(yīng)商類注冊(cè)設(shè)備接口GUID,將體現(xiàn)在注冊(cè)表中,如圖2所示,GUID可用相應(yīng)工具軟件產(chǎn)生。

        圖2 Windows注冊(cè)表中的特定通用USB設(shè)備接口GUID示意圖

        該描述符,供應(yīng)用程序調(diào)用該GUID做讀寫訪問的USB設(shè)備識(shí)別,對(duì)應(yīng)的供應(yīng)商類請(qǐng)求為:

        初次請(qǐng)求--c1 01 00 00 05 00 0a 00,再次請(qǐng)求--c1 01 00 00 05 00 8e 00

        典型的注冊(cè)設(shè)備接口 GUID描述符定義如下:

        const unsigned char itfcGuidDscrpt[] =

        { 0x8E, 0x00, 0x00, 0x00, //包長(zhǎng)(頭+各部分)

        0x00, 0x01, //頭: BCD版本

        0x05, 0x00, //索引

        0x01, 0x00, //數(shù)量

        0x84, 0x00, 0x00, 0x00 //部分: 大小

        0x01, 0x00, 0x00, 0x00, //屬性數(shù)據(jù)類型

        0x28, 0x00, //屬性名字長(zhǎng)度

        { 'D', 0, 'e', 0, 'v', 0, 'i', //屬性名稱[40]:

        0, 'c', 0, 'e', 0, 'I', 0, "DeviceInterfaceGUID"

        'n',0, 't', 0, 'e', 0, 'r',

        0, 'f',0, 'a', 0, 'c', 0,

        'e', 0, 'G',0, 'U', 0,

        'I', 0, 'D', 0, 0, 0

        },

        0x4E, 0x00, //屬性數(shù)據(jù)長(zhǎng)度:

        0x00, 0x00, 78[0x4E]

        { '{', 0, '1', 0, '2', 0, '3', 0, //屬性數(shù)據(jù): {12345678-

        '4', 0, '5', 0, '6', 0, '7', 1234-1234-1234-

        0, 8', 0, '-', 0, '1', 0, '2', 123456789ABC}

        0, '3', 0, '4', 0, '-', 0, '1',

        0, '2', 0, '3', 0, 4', 0, ' '-',

        0, '1', 0, '2', 0, '3', 0, '4',

        0, '-', 0, '1', 0,'2', 0, '3', 0,

        '4', 0, '5', 0, '6', 0, '7', 0,

        8', 0, '9', 0, 'A', 0, 'B', 0,

        'C', 0, '}', 0, 0, 0

        }

        };

        可用作者的“ARM系列微處理控制器的軟件體系架構(gòu)工具”得到完整的STM32103系列USB驅(qū)動(dòng)程序,包括上述3個(gè)特殊描述符在內(nèi)的標(biāo)準(zhǔn)USB請(qǐng)求類和供應(yīng)商請(qǐng)求及其應(yīng)答配置與控制、中斷、批量或同步管道傳輸代碼,限于篇幅,不再贅述。

        2 WinUSB設(shè)備驅(qū)動(dòng)運(yùn)用[3-4,10]

        可視化測(cè)試/應(yīng)用程序中使用Windows OS通用的WinUSB設(shè)備驅(qū)動(dòng),必須引入對(duì)WDK頭文件的引用,需要在可視化窗口.cpp文件頭部加入的典型.h文件引用如下:

        #include "Windows Kits10Include10.0.15063. 0sharedusb.h"

        #include "Windows Kits10Include10.0.15063. 0sharedstrsafe.h"

        #include "Windows Kits10Include10.0.15063. 0umSetupAPI.h"

        #include "Windows Kits10Include10.0.15063. 0umwinusb.h"

        可視化測(cè)試/應(yīng)用程序,通過連接OS底層和應(yīng)用層的WinUSB.dll操作特定的通用WinUSB Device,必須在項(xiàng)目工程中引用WinUSB.dll對(duì)應(yīng)的WinUSB.lib庫文件。WDK提供有相應(yīng)的WinUSB. lib,在Visival Studio中引用沒有問題,但不能直接在Rad Studio XE中引用,編譯連接時(shí)會(huì)報(bào)錯(cuò):

        BCB contains invalid OMF record, type 0x21 (possibly COFF)

        這是IDE要求的原始設(shè)備制造商OEM(Original Equipment Manufacturer)的通用對(duì)象文件格式COFF(Common Object File Format)不同引起的lib文件兼容不足導(dǎo)致的??梢允褂肦ad Studio XE的coff2omf. exe工具進(jìn)行轉(zhuǎn)換再加以引用,命令行操作如下,其中前者是微軟DDK提供的,后者就是得到的Rad Studio XE開發(fā)所需的庫:

        coff2omf -lib:ms WinUSB.lib bcb WinUSB.lib

        3 WinUSB通信傳輸實(shí)現(xiàn)[3-8]

        3.1 WinUSB設(shè)備文件操作

        與其它OS一樣,Winsows把設(shè)備當(dāng)做文件操作,但USB設(shè)備又有特定的集成端點(diǎn)在內(nèi)的管道傳輸?shù)慕涌?,所以打開USB設(shè)備文件后還要打開相應(yīng)的USB接口,得到特定的USB接口操作句柄,之后就可以運(yùn)用該句柄,調(diào)用管道讀寫進(jìn)行數(shù)據(jù)傳輸了??梢暬瘻y(cè)試/應(yīng)用程序退出時(shí)必須依次關(guān)閉USB接口操作句柄和設(shè)備文件操作句柄。

        獲取USB設(shè)備及其接口操作句柄的典型函數(shù)代碼如下:

        HANDLE hDeviceHandle = INVALID_HANDLE_VALUE; // 設(shè)備文件句柄

        WINUSB_INTERFACE_HANDLE hWinUSBHandle // WinUSB操作句柄

        = INVALID_HANDLE_VALUE;

        // USB設(shè)備文件句柄創(chuàng)建[接口GUID,設(shè)備句柄]-------------------------------------------------------------------

        BOOL GetDeviceHandle(GUID guidDeviceInterface, PHANDLE hDeviceHandle )

        { if ( guidDeviceInterface == GUID_NULL ) return FALSE;

        BOOL bResult = TRUE; HDEVINFO hDeviceInfo;

        SP_DEVINFO_DATA DeviceInfoData; DWORD index = 0;

        SP_DEVICE_INTERFACE_DATA deviceInterfaceData;

        PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;

        ULONG requiredLength = 0; LPTSTR lpDevicePath = NULL;

        // 為特定設(shè)備的接口類而獲取安裝設(shè)備的所有信息

        hDeviceInfo = SetupDiGetClassDevs(&guidDeviceInterface, NULL, NULL,

        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );

        if ( hDeviceInfo == INVALID_HANDLE_VALUE ) goto done; // 無效退出

        // 在設(shè)備信息集中枚舉所有設(shè)備接口

        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        for(index=0; SetupDiEnumDeviceInfo(hDeviceInfo, index, & DeviceInfoData); index++)

        { if(lpDevicePath) LocalFree(lpDevicePath); // 復(fù)位相應(yīng)項(xiàng)

        if(pInterfaceDetailData) LocalFree(pInterfaceDetailData);

        deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

        bResult = SetupDiEnumDeviceInterfaces( hDeviceInfo, // 獲取設(shè)備接口信息

        &DeviceInfoData, &guidDeviceInterface, 0, &deviceInterfaceData );

        if(GetLastError()== ERROR_NO_MORE_ITEMS) break; // 最后項(xiàng)?

        if(!bResult) goto done; // 錯(cuò)誤退出

        // 動(dòng)態(tài)調(diào)用2次,首次分配空間,再次得到接口數(shù)據(jù)

        bResult = SetupDiGetDeviceInterfaceDetail( hDeviceInfo,

        &deviceInterfaceData, NULL, 0, &requiredLength, NULL );

        if(!bResult) // 錯(cuò)誤檢查

        { if((ERROR_INSUFFICIENT_BUFFER == GetLastError())

        && ( requiredLength > 0 ) )

        { pInterfaceDetailData = // 動(dòng)態(tài)分配緩沖區(qū)大小

        (PSP_DEVICE_INTERFACE_DETAIL_DATA)

        LocalAlloc(LPTR, requiredLength );

        if (!pInterfaceDetailData ) goto done; // 錯(cuò)誤退出

        }

        else goto done; // 錯(cuò)誤退出

        }

        pInterfaceDetailData->cbSize // 獲取接口詳細(xì)數(shù)據(jù)

        = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        bResult = SetupDiGetDeviceInterfaceDetail( hDeviceInfo,

        &deviceInterfaceData, pInterfaceDetailData,

        requiredLength, NULL, &DeviceInfoData );

        if (!bResult) goto done; // 錯(cuò)誤退出

        size_t nLength = wcslen(pInterfaceDetailData->DevicePath ) + 1; // 設(shè)備文件路徑

        lpDevicePath = (TCHAR *) LocalAlloc( LPTR, nLength * sizeof(TCHAR));

        StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData->DevicePath);

        lpDevicePath[(nLength - 1)] = 0;

        }

        if (!lpDevicePath) goto done; // 錯(cuò)誤退出

        }

        *hDeviceHandle = CreateFile( lpDevicePath, // 打開設(shè)備文件, 得到設(shè)備文件句柄

        GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ

        | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,

        FILE_FLAG_OVERLAPPED, NULL);

        if (*hDeviceHandle != INVALID_HANDLE_VALUE ) return true;

        done: LocalFree( lpDevicePath );

        LocalFree( pInterfaceDetailData );

        bResult = SetupDiDestroyDeviceInfoList( hDeviceInfo );

        return bResult;

        }

        // 獲取設(shè)備的 WinUSB 接口句柄------------------------------------------------------------------------------------

        BOOL GetWinUSBHandle(HANDLE hDeviceHandle,

        PWINUSB_INTERFACE_HANDLE phWinUSBHandle)

        { if(hDeviceHandle == INVALID_HANDLE_VALUE) return FALSE;

        BOOL bResult = WinUsb_Initialize(hDeviceHandle, phWinUSBHandle);

        if (!bResult) return FALSE;

        return bResult;

        }

        可視化窗口,創(chuàng)建時(shí)運(yùn)用特定USB接口GUID,調(diào)用這兩個(gè)函數(shù)創(chuàng)建設(shè)備文件句柄和USB接口操作句柄;窗口關(guān)閉時(shí)依次關(guān)閉這兩個(gè)句柄;若USB設(shè)備沒有掛接,應(yīng)用禁止窗口上所有USB數(shù)據(jù)收發(fā)按鈕操作,相關(guān)核心代碼如下:

        void__fastcall TfrmShow::FormCreate(TObject *Sender)

        {static const GUID stm32F1xxDvcItfc = { 0x-12345678, 0x1234, 0x1344,

        {0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC } };

        GUID guidDeviceInterface = stm32F1xxDvcItfc;

        BOOL bResult = TRUE; ULONG cbSize = 0;

        bResult = GetDeviceHandle(guidDeviceInterface, &hDeviceHandle);

        if (!bResult) return;

        bResult = GetWinUSBHandle(hDeviceHandle, & hWinUSBHandle);

        if(!bResult) return;

        flgWinUSB = true;

        }

        //---------------------------------------------------------

        void __fastcall TfrmShow::FormClose(TObject *Sender, TCloseAction &Action)

        { if(!flgWinUSB) return;

        CloseHandle(hDeviceHandle);

        WinUsb_Free(hWinUSBHandle);

        }

        3.2 收發(fā)傳輸?shù)牟呗钥紤]

        運(yùn)用WinUSB應(yīng)用程序編程接口API (Appli-cation Programming Interface)函數(shù)WinUsb_ReadPipe和WinUsb_WritePipe進(jìn)行數(shù)據(jù)管道收發(fā)傳輸時(shí),若沒有收到或發(fā)出數(shù)據(jù),程序會(huì)一直等待,造成可視化窗口失控,可以通過調(diào)用WinUsb_SetPipePolicy函數(shù),使用WinUSB的超時(shí)管道傳輸策略來避免這種阻塞式的尷尬局面,取消請(qǐng)求之前等待超時(shí)時(shí)間,超過超時(shí)時(shí)間退出等待。通常在USB設(shè)備文件句柄和WinUSB接口句柄創(chuàng)建成功后進(jìn)行超時(shí)傳輸設(shè)置,時(shí)間據(jù)實(shí)際傳輸量而定,典型代碼如下,這里超時(shí)時(shí)間取100ms,0x81對(duì)應(yīng)輸入IN管道1,0x02對(duì)應(yīng)輸出OUT管道2:

        UINT timeout = 100;

        bResult = WinUsb_SetPipePolicy(hWinUSBHandle, 0x81, // 輸入IN管道1

        PIPE_TRANSFER_TIMEOUT, sizeof (timeout), & timeout);

        if(!bResult) return;

        bResult = WinUsb_SetPipePolicy(hWinUSBHandle, 0x02, // 輸出OUT管道2

        PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout);

        if(!bResult) return;

        3.3 數(shù)據(jù)發(fā)送操作實(shí)現(xiàn)

        數(shù)據(jù)發(fā)送,同異步操作差別不大,只要準(zhǔn)備好數(shù)據(jù),很容易知道其數(shù)據(jù)大小,主動(dòng)同步發(fā)出,以最簡(jiǎn)方式實(shí)現(xiàn),典型代碼如下:

        if(hWinUSBHandle==INVALID_HANDLE_VALUE) return;

        UCHAR szBffr[50]; ULONG cbSent = 0;

        AnsiString str = edtSdDt->Text; // 窗口文本輸入控件

        strcpy(szBffr, str.c_str());

        ULONG cbSize = str.Length();

        WinUsb_WritePipe(hWinUSBHandle, 0x02, szBffr, cbSize, &cbSent, 0 );

        3.4 異步數(shù)據(jù)傳輸?shù)膶?shí)現(xiàn)

        異步數(shù)據(jù)收發(fā)傳輸,對(duì)于不知數(shù)據(jù)量大小的操作非常有效,特別是USB管道的讀操作。

        首先需要定義全局的OVERLAPPED結(jié)構(gòu)變量,并在USB設(shè)備文件及其WinUSB接口句柄創(chuàng)建成功后初始化這個(gè)結(jié)構(gòu)變量,主要是其相關(guān)“事件Event”的初始化,典型代碼如下:

        OVERLAPPED overlapped;

        ZeroMemory(&overlapped, sizeof(overlapped));

        overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

        典型的異步USB管道讀事件代碼如下,首先以小固定數(shù)量15進(jìn)行盲讀,在限定的超時(shí)時(shí)間內(nèi),只要收到數(shù)據(jù),都可以接收,并成行顯示在窗口的文本指示框內(nèi):

        void WinUSB_Read(void)

        { if(hWinUSBHandle==INVALID_HANDLE_VALUE) return;

        ULONG cbRead = 0; UCHAR szBffr[20] = {'0'}; AnsiString str;

        BOOL bResult = WinUsb_ReadPipe(hWinUSB-Handle, 0x81,

        szBffr, 15, &cbRead, &overlapped);

        if(bResult)

        { const char* t = szBffr; str = t;

        mRcvDt->Lines->Add(str); // 可視窗口文本顯示控件

        }

        else if(ERROR_IO_PENDING == GetLastError ())

        {bResult = WinUsb_GetOverlappedResult(hW-inUSBHandle, & overlapped, &cbRead, true);

        if(NULL != cbRead)

        { int m = cbRead; cbRead = 0;

        if(bResult)

        { const char* d = szBffr; str = d;

        mmRcvDt->Lines->Add(str);

        }

        }

        }

        }

        3.5 定時(shí)數(shù)據(jù)接收的實(shí)現(xiàn)

        隨時(shí)監(jiān)聽USB輸入管道并接收可能傳入的數(shù)據(jù),在可視化測(cè)試/應(yīng)用程序設(shè)計(jì)中,簡(jiǎn)潔高效的方法就是采用定時(shí)器控制,以一定的時(shí)間間隔,在定時(shí)器的OnTimer事件處理中,去異步的讀取USB輸入管道,典型代碼如下,其中設(shè)置的時(shí)間間隔是100 ms:

        void __fastcall TfrmShow::rcvTmrTimer(TObject *Sender)

        { rcvTmr->Enabled = false; // 關(guān)閉定時(shí)器

        WinUSB_Read(); // 異步數(shù)據(jù)謀取并進(jìn)行可視化窗口顯示

        rcvTmr->Enabled = true; // 重開定時(shí)器

        }

        3.6 后臺(tái)線程數(shù)據(jù)接收實(shí)現(xiàn)

        以線程方式在后臺(tái)進(jìn)行USB輸入管道的監(jiān)聽并接收可能傳入的數(shù)據(jù),是另外一種及時(shí)高效的USB數(shù)據(jù)接收形式。在項(xiàng)目工程中新建線程對(duì)象rcvThrd,進(jìn)而在生成的rcvThrd.h文件中聲明引用的窗口顯示控件和數(shù)據(jù)接收函數(shù)RcvDt(),典型代碼如下:

        class thrdRcvDt : public TThread

        { private: TMemo *memo;

        protected: void __fastcall Execute();

        public: void __fastcall thrdRcvDt::RcvDt();

        __fastcall thrdRcvDt(bool CreateSuspended, TMemo *Amemo);

        };

        在rcvThrd.cpp文件中,聲明所需的包含文件、外部變量,并定義操作函數(shù),典型代碼如下:

        #include "frmStm32Tst.h" // 可視化窗口文件

        #include "Windows Kits10Include10.0.15063. 0sharedusb.h" // DDK文件

        #include "Windows Kits10Include10.0.15063. 0sharedstrsafe.h"

        #include "Windows Kits10Include10.0.15063. 0umSetupAPI.h"

        #include "Windows Kits10Include10.0.15063. 0umwinusb.h"

        extern WINUSB_INTERFACE_HANDLE hWin-USBHandle;

        extern OVERLAPPED overlapped;

        extern void WinUSB_Read(void);

        __fastcall thrdRcvDt::thrdRcvDt(bool Create-Suspended, TMemo *Amemo) : TThread(CreateSu-spended)

        { memo = Amemo; }

        void __fastcall thrdRcvDt::Execute() // 線程執(zhí)行[休眠100ms]

        { while(!Terminated)

        { Synchronize(RcvDt); Sleep(100); }

        }

        void __fastcall thrdRcvDt::RcvDt() // 數(shù)據(jù)異步接收窗口指示

        { WinUSB_Read(); }

        在可視化窗口的frmStm32Tst.h中加入線程對(duì)象包含和線程實(shí)例化聲明,典型代碼如下:

        #include "rcvThrd.h"

        class TfrmShow : public TForm

        { …

        private: thrdRcvDt *rcvThrd;

        }

        在可視化窗口的frmStm32Tst.cpp中,打開設(shè)備文件和WinUSB接口句柄后,啟動(dòng)線程,定義線程終止時(shí)自動(dòng)銷毀,然后運(yùn)行線程,典型代碼如下:

        rcvThrd = new thrdRcvDt(true, mmRcvDt);

        rcvThrd->FreeOnTerminate = true;

        rcvThrd->Resume();

        對(duì)比定時(shí)數(shù)據(jù)接收,異曲同工。定時(shí)器控件,本質(zhì)就是休眠時(shí)間可調(diào)整的線程操作封裝。

        3.7 設(shè)備插撥及相應(yīng)處置

        以上闡述基于先插上USB設(shè)備,再打開可視化測(cè)試/應(yīng)用程序,進(jìn)行通信傳輸,用后關(guān)閉應(yīng)用程序,撥下設(shè)備。而USB設(shè)備即插即用,在USB設(shè)備突然被拔下后,還進(jìn)行讀寫傳輸,程序就阻塞了。為避免這種現(xiàn)象發(fā)生,可創(chuàng)建一個(gè)線程,定時(shí)(如每2s)枚舉檢查相關(guān)的USB設(shè)備,若被拔下,停止定時(shí)數(shù)據(jù)接收或休眠接收線程;若重新插入,則重新創(chuàng)建操作句柄,恢復(fù)定時(shí)數(shù)據(jù)接收或線程數(shù)據(jù)接收。

        4 WinUSB應(yīng)用/測(cè)試程序的發(fā)布[3-4,8]

        4.1 Win8.1以上系統(tǒng)

        應(yīng)用軟件發(fā)布,除Rad Studio產(chǎn)生的.exe文件外,還需要包含WinUSB.lib。若編譯時(shí)不能包含動(dòng)態(tài)庫,還需要包含IDE相關(guān)的cc32240mt.dll和borlndmm.dll。上述各種方法綜合在一起,得到的針對(duì)STM32F103系列微控制USB設(shè)備的WinUSB數(shù)據(jù)收發(fā)測(cè)試的可視化應(yīng)用程序窗口界面如圖3所示:

        圖3 WinUSB數(shù)據(jù)收發(fā)測(cè)試的可視化應(yīng)用程序窗口界面

        4.2 WinXP-Win8系統(tǒng)

        編寫驅(qū)動(dòng)安裝文件.inf,引導(dǎo)OS調(diào)用內(nèi)置的winusb.sys驅(qū)動(dòng)文件的安裝應(yīng)用,主要指明USB設(shè)備的廠商號(hào)、產(chǎn)品號(hào)、USB接口GUID等,通知安裝程序類已設(shè)置為 "USBDevice"。需要使用WinUSB協(xié)助安裝庫文件WinUsbCoInstaller,區(qū)分32位和64位版本,常用版本是V1.9,Win7之后也可以是V1.11。Win7之后系統(tǒng),還需要準(zhǔn)備cat文件,可運(yùn)用WDK的Inf2Cat.exe工具得到,命令行操作如下:

        Inf2Cat.exe /driver:[inf文件目錄] /os: XP_X86, XP_X64,7_X86,7_X64,8_X32,8_X64

        典型inf驅(qū)動(dòng)安裝文件如下:

        [Version]

        Signature="$Windows NT$"

        Class=USBDevice

        ClassGUID={88BAE032-5A81-49f0-BC3D-A4-FF138216D6}

        Provider=%ManufacturerName%

        CatalogFile=instlWinUSB.cat

        DriverVer=01/13/2018,12.4.23.896

        [Manufacturer]

        %ManufacturerName%=Standard,NTx86,NTx64

        [Standard.NTx86]

        %DeviceName%=USB_Install,USBVID_0483& PID_5720

        [Standard.NTx64]

        %DeviceName%=USB_Install,USBVID_0483& PID_5720

        [ClassInstall32]

        AddReg=ClassInstall_AddReg

        [ClassInstall_AddReg]

        HKR,,,,%ClassName%

        HKR,,NoInstallClass,,1

        HKR,,IconPath,%REG_MULTI_SZ%,"C:WindowsSystem32setupapi.dll,-20"

        HKR,,LowerLogoVersion,,5.2

        [USB_Install]

        Include=winusb.inf

        Needs=WINUSB.NT

        [USB_Install.Services]

        Include=winusb.inf

        AddService=WinUsb,0x00000002,WinUsb_Ser-viceInstall

        [WinUsb_ServiceInstall]

        DisplayName=%WinUsb_SvcDesc%

        ServiceType=1

        StartType=3

        ErrorControl=1

        ServiceBinary=C:WindowsSystem32driversWin--USB.sys

        [USB_Install.HW]

        AddReg=Dev_AddReg

        [Dev_AddReg]

        HKR,,DeviceInterfaceGUIDs,0x10000,"{12345678-1234-1344-1234-123456789ABC}"

        [USB_Install.Wdf]

        KmdfService=WINUSB, WinUsb_Install

        [WinUSB_Install]

        KmdfLibraryVersion=1.9

        [USB_Install.CoInstallers]

        AddReg=CoInstallers_AddReg

        CopyFiles=CoInstallers_CopyFiles

        [CoInstallers_AddReg]

        HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller"

        [CoInstallers_CopyFiles]

        WdfCoInstaller01009.dll

        [DestinationDirs]

        CoInstallers_CopyFiles=11

        [SourceDisksNames]

        1=%DiskName%

        [SourceDisksFiles]

        WdfCoInstaller01009.dll=1

        [Strings]

        ManufacturerName="STMicroelectronics"

        ClassName="USB通用串行總線設(shè)備"

        DiskName="kzq"

        WinUsb_SvcDesc="WinUSB Driver"

        DeviceName="STM3210"

        REG_MULTI_SZ = 0x00010000

        5 多WinUSB設(shè)備應(yīng)用測(cè)試的實(shí)現(xiàn)

        多個(gè)同類WinUSB設(shè)備插入同一臺(tái)電腦,系統(tǒng)都可以識(shí)別,通信時(shí)連接傳輸快的USB設(shè)備占主動(dòng)權(quán)后,其它USB設(shè)備就不通信了??梢孕薷腢SB設(shè)備的接口GUID,使連入U(xiǎn)SB設(shè)備差異化,以實(shí)現(xiàn)各個(gè)對(duì)應(yīng)的傳輸通信,找到一個(gè)設(shè)備通信一個(gè),從而實(shí)現(xiàn)類似設(shè)備參數(shù)配置的批量操作實(shí)現(xiàn)。

        6 驅(qū)動(dòng)開發(fā)對(duì)比

        表1 幾種驅(qū)動(dòng)及其開發(fā)對(duì)比表

        Tab.1 Some kind of device drivers and it’s design comparison

        7 結(jié)語

        底層嵌入式應(yīng)用軟件中添加特定描述支持,Windows OS就可以自動(dòng)識(shí)其為WinUSB設(shè)備,上層可視化測(cè)試/應(yīng)用程序就可以通過WinUSB.dll與其進(jìn)行USB數(shù)據(jù)傳輸通信了。這樣,Windows下USB設(shè)備的數(shù)據(jù)采集、監(jiān)視控制、配置參數(shù)、軟件刷新等軟件編程操控,就同傳統(tǒng)的“RS-232C通信”一樣了,無需USB轉(zhuǎn)串口硬軟件轉(zhuǎn)接,而且速度快、實(shí)時(shí)性強(qiáng),直截了當(dāng)。同樣,定時(shí)接收、線程接收、多設(shè)備通信等軟件手段也可以搬來使用,進(jìn)一步提升效率和實(shí)用性。

        [1] CSDN博客. USB設(shè)備描述符舉例說明[EB/OL]. http://blog. csdn.net/u013256018/article/details/60805770?locationNum=10&fps=1, 2017.3.

        [2] CSDN博客﹒WinUSB--微軟為所有USB設(shè)備提供的常規(guī)驅(qū)動(dòng)程序[EB/OL]. http://blog.csdn.net/whw8007/article/details/ 9569989, 2013.8.

        [3] 微軟開發(fā)網(wǎng). 如何通過WinUSB功能訪問USB設(shè)備[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff540174(v=vs.85).aspx, 2017.12.

        [4] 馬開東博客. 如何使用WinUSB與USB設(shè)備USBDevice通信[EB/OL]. http://www.makaidong.com/%E5%8D%9A%E5% AE%A2%E5%9B%AD7/20151013/306670_4.html, 2015.10.

        [5] 微軟開發(fā)網(wǎng). 適用于USB設(shè)備的Windows桌面應(yīng)用[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/ hardware/dn376885(v=vs.85).aspx, 2017.12.

        [6] 微軟開發(fā)網(wǎng). 編寫基于WinUSB模板的Windows桌面應(yīng)用[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/ hardware/dn376872(v=vs.85).aspx, 2017.12.

        [7] 微軟開發(fā)網(wǎng). 用于管道策略修改的WinUSB功能[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff728833(v=vs.85).aspx, 2017.12.

        [8] 怯肇乾等. Windows異步串行通信編程縱橫[J]. 電腦與開發(fā)應(yīng)用, 2009, 6(445): 21-25.

        [9] CSDN博客. winusb--不再為你的usb設(shè)備編寫驅(qū)動(dòng)[EB/OL]. https://blog.csdn.net/phenixyf/article/details/46744419, 2015.7.

        [10] 彭偉. 基于WinUSB與SHT75的溫濕度數(shù)據(jù)采集與控制系統(tǒng)設(shè)計(jì)仿真[J]. 制造業(yè)自動(dòng)化, 2013, 7(15): 129-133.

        Implementation of WinUSB Driver and Its Application in Communication Transmission

        SHI Bao-jing, WANG Chang-xun, KAI Zhao-qian

        (HNCC Electronic Co., LTD, Zhengzhou 450001, China)

        Software design key about WinUSB-Device-Model-Application is how to add descriptor to WinUSB-Device in Windows OS and how to communicate in Windows Application. It’s kernel is how to use timer and thread with asynchronous-data-transmission. Note WinUSB-Application-Publishing in low operating system version, account USB-Plug-in-Plug-out handling and multi-USB-devices-communication. So, Windows USB device data transmission are easy to use such as RS-232C.

        USB descriptor; WinUSB device; Asynchronous data transmission; Data reception with timer; Data reception with thread.

        TP36

        B

        10.3969/j.issn.1003-6970.2018.08.013

        怯肇乾(1969-),男,電子與信息技術(shù)高級(jí)工程師,嵌入式系統(tǒng)設(shè)計(jì)師/培訓(xùn)師,web網(wǎng)絡(luò)測(cè)控軟件系統(tǒng)架構(gòu)師,研究方向?yàn)檐浻布w系及其網(wǎng)絡(luò)系統(tǒng)軟件設(shè)計(jì);石保敬(1977-),男,經(jīng)濟(jì)師,風(fēng)險(xiǎn)評(píng)估師,環(huán)保健康探測(cè)警報(bào)專家,研究方向?yàn)槲:鸵兹家妆瑲怏w探測(cè)產(chǎn)品系統(tǒng)及其開發(fā)設(shè)計(jì);王長(zhǎng)荀(1988-),男,嵌入式硬軟件開發(fā)工程師,研究方向?yàn)檐浻布w系及其網(wǎng)絡(luò)系統(tǒng)軟件設(shè)計(jì)。

        本文著錄格式:石保敬,王長(zhǎng)荀,怯肇乾. WinUSB驅(qū)動(dòng)實(shí)現(xiàn)及其通信傳輸應(yīng)用[J]. 軟件,2018,39(8):57-64

        猜你喜歡
        句柄描述符線程
        基于結(jié)構(gòu)信息的異源遙感圖像局部特征描述符研究
        Linux單線程并發(fā)服務(wù)器探索
        高校圖書館持久標(biāo)識(shí)符應(yīng)用研究
        利用CNN的無人機(jī)遙感影像特征描述符學(xué)習(xí)
        編譯程序語法分析句柄問題分析與探討
        淺談linux多線程協(xié)作
        MFC應(yīng)用程序多線程混合顯示界面方法研究
        基于SPY++的軟件功能擴(kuò)展的研究
        Linux線程實(shí)現(xiàn)技術(shù)研究
        基于PDIUSBD12的USB接口設(shè)計(jì)應(yīng)用研究
        国产精品va在线观看一| 一本一道vs无码中文字幕| 国产精品美女久久久久av超清| 免费无码又爽又刺激聊天app| 国产三级精品三级在线观看| 日韩精品无码久久久久久| www久久久888| 日本久久视频在线观看| av网页免费在线观看| 亚洲国产精品区在线观看| 夜夜爽日日澡人人添| 国产av无码专区亚洲av毛网站| 激情第一区仑乱| 国产欧美一区二区精品仙草咪| 亚洲阿v天堂2018在线观看| 国产在线高清无码不卡| 久久精品伊人久久精品伊人| 被灌醉的日本人妻中文字幕| 国产婷婷色一区二区三区深爱网 | 亚洲熟妇av日韩熟妇在线| 亚洲av国产av综合av| 日韩av一区二区三区四区av| 最新日本免费一区二区三区| 91色老久久偷偷精品蜜臀懂色| 多毛小伙内射老太婆| 午夜精品久久久久久99热| 国产超碰人人模人人爽人人喊| 少妇的诱惑免费在线观看| 国产精品女同二区五区九区| 午夜免费观看日韩一级片| 成人试看120秒体验区| 欧美成人精品一区二区综合| 亚洲一区二区情侣| 蜜桃高清视频在线看免费1 | 国产人妻精品无码av在线| 少妇人妻偷人精品视频| 国产在线视频h| 一区二区免费中文字幕| 一区二区三区亚洲视频 | 奶头又大又白喷奶水av| 欧美v亚洲v日韩v最新在线|