網站導航:首頁開源項目 USB開源項目:Easy USB 51 Programer  

目錄導航

   
  1、項目簡介
USB開發基礎
1、USB接口的優點及開發難易度
2、USB設備的開發流程
3、USB接口芯片(USB控制器)的選擇
4、了解USB的通訊過程
5、USB命令(請求)和USB描述符
6、實例講解USB的枚舉(配置)過程
准備工作
1、需要哪些工具
2、電路原理圖
3、手工制作您的電路板
4、測試您的硬件
HID設備類
1、讓PC機找到我們的硬件
2、如何成爲一個HID設備(模擬鼠標)
3、如何成爲一個HID設備(模擬鍵盤)
4、如何與HID設備通訊(一)
5、如何與HID設備通訊(二)
6、51編程器的實現
Windows USB 驱动程序(自定义设备)
1、Windows驅動開發基礎
2、開發環境配置
3、第一个实例-Hello Wdm(一)
4、第一个实例-Hello Wdm(二)
5、真正的實例—驅動我們的實驗板
6、真正的實例—測試驅動程序
7、真正的實例—控制LED及讀取按鍵狀態
8、如何編寫應用程序
   

相关産品    淘寶網店
     
 

 
  更多...  
 
 
如何與HID設備通訊(二) 查看/参与此開源項目相关讨论
 

三、讀寫HID設備的步驟

  讀寫HID設備步驟如下:

①、得到系統HID設備結構數組指針
②、對設備進行遍曆
③、得到指定HID設備的句柄
④、readfile/writefile進行讀寫

  下面分別對各步驟及其所涉及的相關API函數進行介紹。

1、得到設備句柄:這步用到的兩面個主要API函數原型爲:

A、通過以下函數

 
  1. VOID  HidD_GetHidGuid(OUT LPGUID  HidGuid    );  

得到HID設備的GUID。

B、再通過以下函數

 
  1. HDEVINFO SetupDiGetClassDevs(   
  2.   CONST LPGUID ClassGuid,    
  3.   PCTSTR Enumerator,    
  4.   HWND hwndParent,    
  5.   DWORD Flags   
  6. );  

取得HID設備結構數組指針,以便下一步利用這個數組對所有HID設備進行遍列。

2、對設備進行遍曆:遍曆過程如下

A、首先執行以下函數:

 
  1. WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfaces(   
  2.     IN HDEVINFO  DeviceInfoSet,   
  3.     IN PSP_DEVINFO_DATA  DeviceInfoData  OPTIONAL,   
  4.     IN LPGUID  InterfaceClassGuid,   
  5.     IN DWORD  MemberIndex,   
  6.     OUT PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);  

運行此函數的主要目的是取得第一個參數DeviceInfoSet的填充值,又將此值作爲以下函數

 
  1. BOOL SetupDiGetDeviceInterfaceDetail(   
  2.     HDEVINFO DeviceInfoSet,    
  3.     PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,    
  4.     PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,    
  5.     DWORD DeviceInterfaceDetailDataSize,    
  6.     PDWORD RequiredSize,    
  7.     PSP_DEVINFO_DATA DeviceInfoData);   

的第一個參數,以便取得這個函數的第三個參數DeviceInterfaceDetailData的填充值,然後利用這個值傳遞給CreateFile函數,此時CreateFile會返回一個指向HID設備的句柄,再根據以下函數

 
  1. BOOLEAN  HidD_GetAttributes(   
  2.     IN HANDLE  HidDeviceObject,   
  3.     OUT PHIDD_ATTRIBUTES  Attributes   
  4.     );  

取得此HID設備的屬性(第二個參數的填充值),然後判斷屬性裏的PID(Attributes->ProductID)和VID(Attributes->VendorID)是否是我們要查找的設備的PID和VID。PID和VID在下位機固件代碼的設備描述符裏提供(設備描述裏的idProduct域和idVendor,參考百合電子工作室發表的文章《USB開發基礎--USB命令(请求)和USB描述符》一文中表4),當然您也可以通過一些工具查詢得到PID和VID,您可以到USB組織官方網站www.usb.org下載這類工具。

3、根據得到的設備句柄利用ReadFile和WriteFile對設備進行讀寫操作。

  百合電子工作室已經將以上步驟封裝成了一個HID類(參考了其它一些實例代碼),它能實現對指定PID和VID設備的查找,並實現了數據收發功能,同時具有設備撥插檢測通知功能。點擊這裏下載

下面用實例說明如何使用這個類。

 四、讀寫HID設備實例

实例 1

1、找开Visual C++ 6.0,新建一基于MFC的工程名为:Easy USB 51 Programer Test1。

2、MFC AppWizard Step 1对话框中选择基于对话框的应用程序,然后点“Finish”按钮,如图所示:

3、创建3个静态文本标签(Static Text),文本内容分别为:Write、Read和Message;创建两个文本框和一个列表框,ID分别为:IDC_EDIT_TX、IDC_EDIT_RX和IDC_LIST_MESSAGE;两个按钮ID和文本分别为:IDC_BTN_WRITE(Write)和IDCANCEL(Exit)。界面如下:

4、添加控件所對應的變量,如下圖所示:

5、将Hid.c和Hid.h导入工程,并将“要用到的windows ddk里的几个文件”文件夹内的文件复制到工程所在目录,在Procect->Settings->Link页的“Object/Library moudles”设置中添加“hid.lib setupapi.lib”,如下图所示:

6、在stdafx.h文件中包含头文件语句前添加:#define WINVER  0x0500

7、修改Hid.c中的PID和VID宏定義來設置需要訪問的HID設備,此處的PID和VID值分別爲0x0666和0x0471:

 
  1. #define VID 0x0471   
  2. #define PID 0x0666  

8、在CEasyUSB51ProgramerTest1Dlg類中添加成員變量m_MyHidDevice,其定義如下

 
  1. CHid m_MyHidDevice;  

當然您得包含頭文件Hid.h。

9、在CEasyUSB51ProgramerTest1Dlg類的OnInitDialog函數中添加如下語句:

 
  1. m_MyHidDevice.m_hParentWnd = (HANDLE*) this->GetSafeHwnd( );   
  2. if(m_MyHidDevice.FindHid())     //找到指定HID設備   
  3. {   
  4.     m_ctrlMessage.InsertString(-1,"My hid device detected");   
  5. }   
  6. else                            //沒有找到指定HID設備   
  7. {   
  8.     m_ctrlMessage.InsertString(-1,"My hid device not detected");   
  9.     m_ctrlWrite.EnableWindow(FALSE);    //禁用"write"按鈕   
  10. }  

10、在CEasyUSB51ProgramerTest1Dlg的消息映射中(“BEGIN_MESSAGE_MAP(CEasyUSB51ProgramerTest1Dlg, CDialog)” 与 “END_MESSAGE_MAP()”之间)添加如下代码:

 
  1. ON_MESSAGE(WM_DEVICECHANGE, OnDeviceChange)  

11、在CEasyUSB51ProgramerTest1Dlg類中添加成員函數:

 
  1. LRESULT OnDeviceChange(WPARAM wParam, LPARAM lParam);  

12、成員函數OnDeviceChange的結構如下:

 
  1. LRESULT CEasyUSB51ProgramerTest1Dlg::OnDeviceChange(WPARAM wParam, LPARAM lParam)   
  2. {   
  3.        
  4.     /* take the appropriate action for the message */  
  5.     switch(LOWORD(wParam))    
  6.     {   
  7.            
  8.         /* HID device arrival */  
  9.         case DBT_DEVICEARRIVAL:   
  10.         {   
  11.             /* try to open a handle to the device */  
  12.             if(m_MyHidDevice.FindHid()) /*此處必須調用FindHid()判斷是否是“ 我”的HID設備插入USB口*/  
  13.             {   
  14.                 /*檢測到指定的HID設備插入USB口*/  
  15.                 /*您在這裏可以添加其它功能代碼*/                 
  16.             }   
  17.             break;   
  18.         }   
  19.   
  20.         /* HID device removal */  
  21.         case DBT_DEVICEREMOVECOMPLETE:   
  22.         {   
  23.             if(!m_MyHidDevice.FindHid())    /*此處必須調用FindHid()判斷是否是“ 我”的HID設備撥出USB口*/  
  24.             {   
  25.                 /*檢測到指定的HID設備撥出USB口*/  
  26.                 /*您在這裏可以添加其它功能代碼*/                 
  27.             }   
  28.             break;   
  29.         }   
  30.     }   
  31.   
  32.     return true;   
  33. }  

13、這裏爲了實現在Message信息框裏顯示HID設備的撥插操作,現對OnDeviceChange函數作如下填充:

 
  1. LRESULT CEasyUSB51ProgramerTest1Dlg::OnDeviceChange(WPARAM wParam, LPARAM lParam)   
  2. {   
  3.        
  4.     /* take the appropriate action for the message */  
  5.     switch(LOWORD(wParam))    
  6.     {   
  7.            
  8.         /* HID device arrival */  
  9.         case DBT_DEVICEARRIVAL:   
  10.         {   
  11.             /* try to open a handle to the device */  
  12.             if(m_MyHidDevice.FindHid()) /*此處必須調用FindHid()判斷是否是“ 我”的HID設備插入USB口*/  
  13.             {   
  14.                 /*檢測到指定的HID設備插入USB口*/  
  15.                 /*您在這裏可以添加其它功能代碼*/  
  16.                 unsigned short nIndex   = m_ctrlMessage.InsertString(-1,"My hid device detected");   
  17.                 m_ctrlMessage.SetCurSel(nIndex);    //流動信息窗口   
  18.                 m_ctrlWrite.EnableWindow(TRUE);     //啓用"write"按鈕   
  19.             }   
  20.             break;   
  21.         }   
  22.   
  23.         /* HID device removal */  
  24.         case DBT_DEVICEREMOVECOMPLETE:   
  25.         {   
  26.             if(!m_MyHidDevice.FindHid())    /*此處必須調用FindHid()判斷是否是“ 我”的HID設備撥出USB口*/  
  27.             {   
  28.                 /*檢測到指定的HID設備撥出USB口*/  
  29.                 /*您在這裏可以添加其它功能代碼*/  
  30.                 unsigned short nIndex   = m_ctrlMessage.InsertString(-1,"My hid device removed");   
  31.                 m_ctrlMessage.SetCurSel(nIndex);    //流動信息窗口   
  32.                 m_ctrlWrite.EnableWindow(FALSE);    //禁用"write"按鈕   
  33.             }   
  34.             break;   
  35.         }   
  36.     }   
  37.   
  38.     return true;   
  39. }  

 14、對HID的讀寫可通過Hid類的成員函數WriteHid和ReadHid。以下是"write"按鈕的響應函數,實現對HID設備的讀寫操作:

 
  1. void CEasyUSB51ProgramerTest1Dlg::OnBtnWrite()    
  2. {   
  3.     unsigned char ucTxBuffer[64];   //發送緩沖   
  4.     unsigned char ucRxBuffer[64];   //接收緩沖   
  5.   
  6.     UpdateData(TRUE);   
  7.   
  8.     //判斷發送框中內容是否超過64字節   
  9.     if(m_strTx.GetLength()>64)   
  10.     {   
  11.         AfxMessageBox("發送字節數不能超過64個字節");   
  12.     }   
  13.   
  14.     //准備發送緩沖區中的內容   
  15.     for(int i=0; i<64 ; i++)   
  16.     {   
  17.         if(i <= (m_strTx.GetLength()-1) )   
  18.             ucTxBuffer[i]   = m_strTx.GetAt(i);   
  19.         else  
  20.             ucTxBuffer[i]   = 0;   
  21.     }   
  22.   
  23.     //寫操作   
  24.     m_MyHidDevice.WriteHid(ucTxBuffer,64);   
  25.     //讀操作   
  26.     m_MyHidDevice.ReadHid(ucRxBuffer,64);   
  27.   
  28.     m_strRx     = ucRxBuffer;   
  29.     UpdateData(FALSE);   
  30. }  

完成後的實際效果:

下載程序

下載源代碼

实例 2

  此例子需要用到扩展板:EXT-BOARD-A。实现功能为通过上位机设定 EXT-BOARD-A 上的8个发光二极管状态。

 1、命令及數據定義

  下位機已經規定了每幀數據的長度爲64個字節,我們現在需要對每一個字節的含義作出定義。在這個實例中,我們可作如下規定:每幀數據前5個字節爲命令,命令後面緊跟數據(從第6個字節開始)。命令爲ASCII編碼,在此實例中只有一個命令“ENLED”,代表設備LED狀態。命令後面的一個字節爲數據,代表D0~D7八個LED的狀態,後面的字節無意義。

2、修改下位機程序

  修改main.c文件,其內容如下:

 
  1. /********************************Copyright (c)**************************************************  
  2. **                               百合電子工作室  
  3. **                                 
  4. **                                  
  5. **  
  6. **                              
  7. **  
  8. ** 文   件   名: main.c  
  9. ** 最後修改日期: 2008年12月25日  
  10. ** 描        述: 用戶應用程序  
  11. ** 版          本: V6.0  
  12. **********************************************************************************************************/  
  13.   
  14. //#include <at89x52.h>   
  15. #include <reg51.h>   
  16. #include "D12Config.h"   
  17. #include "Descriptor.h"   
  18. #include "Chap_9.h"   
  19. #include "D12Driver.h"   
  20. #include <string.h>   
  21.   
  22. main()   
  23. {      
  24.     unsigned char ucLedState;   
  25.        
  26.     if (Init_D12()!=0)                  //初始化D12   
  27.         return;                         //如果初始化不成功,返回   
  28.        
  29.     IT0 = 0;                            //外部中斷0爲電平觸發方式   
  30.        
  31.     EX0 = 1;                            //開外部中斷0   
  32.     PX0 = 0;                            //設置外部中斷0中斷優先級   
  33.     EA = 1;                             //開80C51總中斷    
  34.        
  35.     while(1)   
  36.     {   
  37.         usbserve();                     //處理USB事件   
  38.         if(bEPPflags.bits.configuration)       
  39.         {       
  40.             //在這裏添加端點操作代碼     
  41.                
  42.             if(bEPPflags.bits.ep2_rxdone )  //主端點接收到數據(從主機發往設備的數據)       
  43.             {       
  44.                 bEPPflags.bits.ep2_rxdone       = 0;           
  45.                    
  46.                 //判斷是否是 ENLED 命令(EpBuf的前5個字節爲”ENLED“)            
  47.                 if(strncmp("ENLED",EpBuf,5)==0)   
  48.                 {   
  49.                     //取得LED狀態設定值   
  50.                     ucLedState  = EpBuf[5];   
  51.                        
  52.                     //設定LED狀態   
  53.                     P0  = ucLedState;   
  54.                 }                          
  55.             }        
  56.         }     
  57.     }   
  58. }   

 點擊這裏下載修改好的源代码

 3、上位機程序

  通過實例1的學習,其實上位機程序的編寫非常簡單,所以在這裏只貼出源代碼。

                                           
            

              上位机界面                                               LED的状态由上位机控制

 下載程序

 下載源代碼

 
 
 
本站程序由百合電子工作室开发和维护
Copyright @ baihe electric studio
渝ICP備09006681號-4