網站導航:首頁開源項目 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設備(模擬鼠標) 查看/参与此開源項目相关讨论
 

  通過上一節的工作,PC機能成功發現USB設備的插入,但是PC要求我們提供此設置的驅動程序,這是因爲原固件驅動定義的設備類型是“測試設備類”,此時要求用戶提供自定義的設備驅動程序,如下圖所示:

  USB主機是通過請求設備的相關描述符來判斷設備類型的,所以我們只需要修改相關描述符就能實現我們想要設備類型。描述符的配置位于Descriptor.h和Descriptor.c文件中。

  下面我们来把Easy USB 51 Programer改造成一个鼠標。

第一步:修改Descriptor.c

 1、找到設備描述結構體

 
  1. //設備描述符   
  2. code USB_DEVICE_DESCRIPTOR DeviceDescr =   
  3. {   
  4.     sizeof(USB_DEVICE_DESCRIPTOR),              //設備描述符长度,= 12H   
  5.     USB_DEVICE_DESCRIPTOR_TYPE,             //設備描述符类型,= 01H   
  6.     0x00,0x01,                      //協議版本,= 1.10   
  7.     USB_CLASS_CODE_TEST_CLASS_DEVICE,           //測試設備類型, = 0DCH       
  8.     0, 0,                           //設備子類,設備協議   
  9.     EP0_PACKET_SIZE,                    //端點0最大數據包大小,= 10H     
  10.     0x71,0x04,                      //PHILIPS公司的設備ID       
  11.     0x66,0x01,                      //设备制造商定的産品ID   
  12.     0x00,0x01,                      //設備系列號   
  13.     0, 0, 0,                        //索引   
  14.     1                                           //可能的配置數   
  15. };  

將其中的

 
  1. USB_CLASS_CODE_TEST_CLASS_DEVICE,           //測試設備類型, = 0DCH  

注釋掉,並在其後加入下面這行代碼

 
  1. 0,                            //設備類型由接口描述符提供  

同時也將

 
  1. 0x66,0x01,                      //设备制造商定的産品ID   

修改爲

 
  1. 0x66,0x02,                      //设备制造商定的産品ID   

 

2、找到接口描述符結構體

 
  1. //接口描述符   
  2. {   
  3.     sizeof(USB_INTERFACE_DESCRIPTOR),           //接口描述符長度,= 09H   
  4.     USB_INTERFACE_DESCRIPTOR_TYPE,              //接口描述符類型,= 04H   
  5.     0,                          //接口數,只有1個   
  6.     0,                          //可選配置,只有1個   
  7.     NUM_ENDPOINTS,                      //除端點0的端點索引數目,= 04H   
  8.     USB_CLASS_CODE_TEST_CLASS_DEVICE,           //測試設備類型,= 0DCH   
  9.     USB_SUBCLASS_CODE_TEST_CLASS_D12,           //子類代碼,= 0A0H      
  10.     USB_PROTOCOL_CODE_TEST_CLASS_D12,           //協議代碼,= 0B0H   
  11.     0                                           //字符串描述符索引   
  12. },  

將其中的

 
  1. USB_CLASS_CODE_TEST_CLASS_DEVICE,            //測試設備類型,= 0DCH  

注釋掉,並在其後加入下面一行代碼

 
  1. 0x03,                                           //人機接口設備(HID)類  

  第二步:編譯源程序並寫入主控芯片

  將我們的編程器插入PC機,激動人心的時刻到了,我們看到PC機能成功識別到我們插入的設備是人體工學設備(就是HID設備)了:

  但是接下來卻提示:

  打开设备管理器我们发现人体学输入设备下面有一个USB设备出现了“!”号,这个设备就是我们的Easy USB 51 Programer,但为什么有问题呢

  看來是我們對USB設備的枚舉過程不夠了解,您可以先看看百合電子工作室發表的文章:USB開發基礎--实例讲解USB的枚举(配置)过程USB HID 设备类协议入门。 

第三步:繼續修改

   《USB HID 设备类协议入门》一文中提到,除了HID的三個特定描述符組成對HID設備的解釋外,5個標准描述符中與HID設備有關的部分有:

  • 設備描述符中bDeviceClass、bDeviceSubClass和bDeviceProtocol三個字段的值必須爲零。
  • 接口描述符中bInterfaceClass的值必须为0x03,bInterfaceSubClass的值为0或1,为1表示HID设备符是一个启动设备(Boot Device,一般对PC机而言才有意义,意思是BIOS启动时能识别并使用您的HID设备,且只有标准鼠標或鍵盤类设备才能成为Boot Device。 bInterfaceProtocol的取值含義如下表所示: 

    HID接口描述符中bInterfaceProtocol的含義
    bInterfaceProtocol的取值(十進制) 含義
    0 NONE
    1 鼠標
    2 鍵盤
    3~255 保留

所以我們還有兩處沒有修改到:

A、找到:

 
  1. USB_SUBCLASS_CODE_TEST_CLASS_D12,           //子類代碼,= 0A0H  

將其注釋掉並在其後加入以下代碼:

 
  1. 1,                          //使用的子類:(支持boot)  

B、找到:

 
  1. USB_PROTOCOL_CODE_TEST_CLASS_D12,           //協議代碼,= 0B0H  

將其注釋掉,並在其後加入以下代碼:  

 
  1. 1,                                      //bInterfaceProtocol为1代表鼠標  

虽然我们将接口描述符中的bInterfaceProtocol设为1(代表鼠標),但这只是针对启动设备(Boot Device)而言有才有效果(即PC机的BIOS加载后能识别和使用),但真正对HID设备的数据流格式进行描述的是报告描述符,所以 bInterfaceProtocol的取值实际意义不大。

  对标准描述符的修改已经完成了,但是到目前为止还不能让我们的HID设备运行起来,因为HID設備類还有3个特定的描述符,它们分别是:HID描述符、报告描述符和实体描述符,其中实体描述符是可选描述符。

  USB主机在请求HID设备的配置描述符时,设备返回的描述符为:配置描述符、接口描述符、HID描述符、端点描述符。HID描述符里包含了其附属的描述的类型和长度(如报告描述符),然后主机再根据HID描述符的信息请求其相关的描述符。所以我们现在来完成HID設備類的两必须的类特定描述符:HID描述符和报告描述符。

1、修改Descriptor.c

A、將以下代碼

 
  1. 0x60,                           //自供電,支持遠程喚醒  

修改爲

 
  1. 0x80,                           //總線供電  

B、在以下代碼

 
  1. //端點描述符,端點1輸入   
  2. {   
  3.     sizeof(USB_ENDPOINT_DESCRIPTOR),            //端點描述符長度,= 07H   
  4.     USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  5.     0x81,                                       //端點1 IN   
  6.     USB_ENDPOINT_TYPE_INTERRUPT,                //中斷傳輸, = 03H   
  7.     EP1_PACKET_SIZE,0x00,                       //端點最大包的大小,= 0010H   
  8.     10                                          //傳輸間隔時間,= 10ms   
  9. },  

前面加入代碼:

 
  1. //hid_descriptor   
  2. {   
  3.     sizeof(USB_HID_DESCRIPTOR),                                     //HID描述符的字節數大小 0x09   
  4.     USB_HID_DESCRIPTOR_TYPE,                                //HID描述符類型編號0x21   
  5.     SWAP16(0x0110),                                         //協議版本,= 1.10   
  6.     0x21,                                                   //固件的國家地區代號,0x21爲美國   
  7.     NUM_SUB_DESCRIPTORS,                                    //下級描述符的數量   
  8.     USB_REPORT_DESCRIPTOR_TYPE,                             //下級描述符爲報告描述符   
  9.     SWAP16(sizeof(MouseReportDescriptor)),               //下級描述符的長度   
  10. },  

其中USB_HID_DESCRIPTOR为HID描述符结构体,在Descriptor中定义;SWAP16为宏定义,作用是交换双字節数据的高字節和低字節,在Descriptor.h中定义;MouseReportDescriptor为HID报告描述符,我们可利用HID Descriptor tool来生成,这是一个标准鼠標的报告描述符。

C、在代碼

 
  1. /* 接口描述符: 協議代碼 */  
  2. #define USB_PROTOCOL_CODE_TEST_CLASS_D12                    0xB0  

後面加入以下代碼:

 
  1. //該報告描述符號由HID Descriptor tool生成   
  2. code char MouseReportDescriptor[63] = {   
  3.     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)   
  4.     0x09, 0x06,                  // USAGE (Keyboard)   
  5.     0xa1, 0x01,                    // COLLECTION (Application)   
  6.     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)   
  7.     0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)   
  8.     0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)   
  9.     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)   
  10.     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)   
  11.     0x75, 0x01,                    //   REPORT_SIZE (1)   
  12.     0x95, 0x08,                    //   REPORT_COUNT (8)   
  13.     0x81, 0x02,                    //   INPUT (Data,Var,Abs)   
  14.     0x95, 0x01,                    //   REPORT_COUNT (1)   
  15.     0x75, 0x08,                    //   REPORT_SIZE (8)   
  16.     0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)   
  17.     0x95, 0x05,                    //   REPORT_COUNT (5)   
  18.     0x75, 0x01,                    //   REPORT_SIZE (1)   
  19.     0x05, 0x08,                    //   USAGE_PAGE (LEDs)   
  20.     0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)   
  21.     0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)   
  22.     0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)   
  23.     0x95, 0x01,                    //   REPORT_COUNT (1)   
  24.     0x75, 0x03,                    //   REPORT_SIZE (3)   
  25.     0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)   
  26.     0x95, 0x06,                    //   REPORT_COUNT (6)   
  27.     0x75, 0x08,                    //   REPORT_SIZE (8)   
  28.     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)   
  29.     0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)   
  30.     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)   
  31.     0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))   
  32.     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)   
  33.     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)   
  34.     0xc0                           // END_COLLECTION           
  35. };  

D、將以下代碼注釋掉

 
  1. //端點描述符,端點1輸入   
  2. {   
  3.     sizeof(USB_ENDPOINT_DESCRIPTOR),            //端點描述符長度,= 07H   
  4.     USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  5.     0x81,                                       //端點1 IN   
  6.     USB_ENDPOINT_TYPE_INTERRUPT,                //中斷傳輸, = 03H   
  7.     EP1_PACKET_SIZE,0x00,                       //端點最大包的大小,= 0010H   
  8.     10                                          //傳輸間隔時間,= 10ms   
  9. },   
  10. //端點描述符,端點1輸出   
  11. {   
  12.     sizeof(USB_ENDPOINT_DESCRIPTOR),            //端點描述符長度,= 07H   
  13.     USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  14.     0x1,                                        //端點1 OUT   
  15.     USB_ENDPOINT_TYPE_INTERRUPT,                //中斷傳輸,= 03H   
  16.     EP1_PACKET_SIZE,0x00,                       //端點最大包的大小,= 0010H   
  17.     10                                          //傳輸間隔時間,= 10ms   
  18. },  

E、將以下代碼

 
  1. //端點2輸入   
  2. {   
  3.     sizeof(USB_ENDPOINT_DESCRIPTOR),            //端點描述符長度,= 07H   
  4.     USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  5.     0x82,                                       //端點2 OUT   
  6.     USB_ENDPOINT_TYPE_BULK,                     //批量傳輸,= 02H   
  7.     EP2_PACKET_SIZE,0x00,                       //端點最大包的大小,= 0040H   
  8.     10                                          //批量傳輸時該設備無效   
  9. },   
  10. //端點2輸出   
  11. {   
  12.     sizeof(USB_ENDPOINT_DESCRIPTOR),            //端點描述符長度,= 07H   
  13.     USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  14.     0x2,                                        //端點2 IN       
  15.     USB_ENDPOINT_TYPE_BULK,                     //批量傳輸,= 02H   
  16.     EP2_PACKET_SIZE,0x00,                       //端點最大包的大小,= 0040H   
  17.     10                                          //批量傳輸時該設備無效   
  18. }   

修改爲

 
  1. //端點2輸入   
  2.     {   
  3.         sizeof(USB_ENDPOINT_DESCRIPTOR),        //端點描述符長度,= 07H   
  4.         USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  5.         0x82,                                       //端點2 OUT   
  6.         USB_ENDPOINT_TYPE_INTERRUPT,                        //中斷傳輸,= 03H   
  7.         EP2_PACKET_SIZE,0x00,                               //端點最大包的大小,= 0040H   
  8.         0x01                                                                //中斷掃描時間:設置爲1ms   
  9.     },   
  10. //端點2輸出   
  11.     {   
  12.         sizeof(USB_ENDPOINT_DESCRIPTOR),        //端點描述符長度,= 07H   
  13.         USB_ENDPOINT_DESCRIPTOR_TYPE,               //端點描述符類型,= 05H   
  14.         0x02,                                       //端點2 IN       
  15.         USB_ENDPOINT_TYPE_INTERRUPT,                        //中斷傳輸,= 03H   
  16.         EP2_PACKET_SIZE,0x00,                               //端點最大包的大小,= 0040H   
  17.         0x01                                                                //中斷掃描時間:設置爲1ms   
  18.     }   

2、修改Descriptor.h

A、將以下代碼

 
  1. /***********  D12 USB 各種描述符結構體 *********************/  
  2. typedef struct _USB_DESCRIPTOR {   
  3.     USB_CONFIGURATION_DESCRIPTOR ConfigDescr;       //配置描述符   
  4.     USB_INTERFACE_DESCRIPTOR InterfaceDescr;        //接口描述符   
  5.     USB_ENDPOINT_DESCRIPTOR EP1_TXDescr;            //端點1輸入描述符   
  6.     USB_ENDPOINT_DESCRIPTOR EP1_RXDescr;            //端點1輸出描述符   
  7.     USB_ENDPOINT_DESCRIPTOR EP2_TXDescr;            //端點2輸入描述符   
  8.     USB_ENDPOINT_DESCRIPTOR EP2_RXDescr;            //端點2輸出描述符   
  9. } USB_DESCRIPTOR, *PUSB_DESCRIPTOR;  

修改爲

 
  1. /***********  D12 USB 各種描述符結構體 *********************/  
  2. typedef struct _USB_DESCRIPTOR {   
  3.     USB_CONFIGURATION_DESCRIPTOR ConfigDescr;       //配置描述符   
  4.     USB_INTERFACE_DESCRIPTOR InterfaceDescr;        //接口描述符   
  5.     USB_HID_DESCRIPTOR HidDescr;                    //HID描述符   
  6. //  USB_ENDPOINT_DESCRIPTOR EP1_TXDescr;            //端點1輸入描述符   
  7. //  USB_ENDPOINT_DESCRIPTOR EP1_RXDescr;            //端點1輸出描述符   
  8.     USB_ENDPOINT_DESCRIPTOR EP2_TXDescr;            //端點2輸入描述符   
  9.     USB_ENDPOINT_DESCRIPTOR EP2_RXDescr;            //端點2輸出描述符   
  10. } USB_DESCRIPTOR, *PUSB_DESCRIPTOR;  

B、找到以下代碼段:

 
  1. /***********  USB HUB 描述符結構體  ***************/  
  2. typedef struct _USB_HUB_DESCRIPTOR {   
  3.     INT8U        bDescriptorLength;      // Length of this descriptor   
  4.     INT8U        bDescriptorType;        // Hub configuration type   
  5.     INT8U        bNumberOfPorts;         // number of ports on this hub   
  6.     INT16U       wHubCharacteristics;    // Hub Charateristics   
  7.     INT8U        bPowerOnToPowerGood;    // port power on till power good in 2ms   
  8.     INT8U        bHubControlCurrent;     // max current in mA   
  9.     //   
  10.     // room for 255 ports power control and removable bitmask   
  11.     INT8U        bRemoveAndPowerMask[64];   
  12. } USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;  

在其後加入代碼:

 
  1. #define NUM_SUB_DESCRIPTORS 1   
  2.   
  3. /*********** 定義HID描述符結構  ***************/  
  4. typedef struct _HID_DESCRIPTOR   
  5. {   
  6.  INT8U bLength;   
  7.  INT8U bDescriptorType;   
  8.  INT16U bcdHID;   
  9.  INT8U bCountryCode;   
  10.  INT8U bNumDescriptors;   
  11. // USB_HID_SUB_DESCRIPTOR HidSubDescriptors[NUM_SUB_DESCRIPTORS];   
  12.  INT8U bSubDescriptorType;    //下級描述符的類型編號   
  13.  INT16U wDescriptorLength;  //下級描述符的長度   
  14. }USB_HID_DESCRIPTOR,*PUSB_HID_DESCRIPTOR;  

C、找到以下代碼:

 
  1. #define USB_POWER_DESCRIPTOR_TYPE                 0x06  

在其後加入

 
  1. #define USB_HID_DESCRIPTOR_TYPE             0x21    //HID描述符類型   
  2. #define USB_REPORT_DESCRIPTOR_TYPE      0x22  //報告描述符  

 D、找到以下代碼:

 
  1. #define __HIDDESCRIPTOR_H__  

在其後加入

 
  1. #define SWAP16(x)  ((((INT16U)(x))<<8)|(((INT16U)(x))>>8))   
  2.   
  3. extern code char MouseReportDescriptor[63];  

 E、將以下代碼

 
  1. #define NUM_ENDPOINTS   4  

修改爲

 
  1. #define NUM_ENDPOINTS   2  

F、將以下代碼

 
  1. #define CONFIG_DESCRIPTOR_LENGTH    sizeof(USB_CONFIGURATION_DESCRIPTOR) \   
  2.                                     + sizeof(USB_INTERFACE_DESCRIPTOR) \   
  3.                                     + (NUM_ENDPOINTS * sizeof(USB_ENDPOINT_DESCRIPTOR))  

修改爲

 
  1. #define CONFIG_DESCRIPTOR_LENGTH    sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_HID_DESCRIPTOR) + (NUM_ENDPOINTS * sizeof(USB_ENDPOINT_DESCRIPTOR))  

3、修改Chap_9.c

  以下修改內容主要與實現與HID類相關請求有關。

A、将get_descriptor函数注释掉,并修改爲

 
  1. void get_descriptor(void)   
  2. {   
  3.     INT8U bDescriptor = MSB(ControlData.DeviceRequest.wValue);          //讀取請求的描述符類型   
  4.             //wValue的高字節表示描述符的類型,低字節表示描述符的索引值   
  5.        
  6.   
  7.     if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE) //獲取設備描述符   
  8.     {          
  9.         code_transmit((INT8U *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR));   
  10.     }   
  11.     else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE) //獲取配置描述符   
  12.     {          
  13.         if (ControlData.DeviceRequest.wLength > CONFIG_DESCRIPTOR_LENGTH)   
  14.         {    
  15.             ControlData.DeviceRequest.wLength = CONFIG_DESCRIPTOR_LENGTH;   
  16.         }   
  17.         code_transmit((INT8U *)&(usb_descr.ConfigDescr), ControlData.DeviceRequest.wLength);   
  18.                                                                        
  19.   
  20.     //發送描述符內容   
  21.     }   
  22.     //---------------(added by BH.)------------------------------   
  23.   
  24.     else if(bDescriptor == USB_REPORT_DESCRIPTOR_TYPE)  //獲取報告描述符   
  25.     {   
  26.            
  27. //      ControlData.wCount=SWAP16(sizeof(KeyBoardReportDescriptor));   
  28.         ControlData.pData=(INT8U *)(MouseReportDescriptor);   
  29. //      if(ControlData.wLength<ControlData.wCount)   
  30. //          ControlData.wCount = ControlData.wLength;   
  31.                
  32. //      code_transmit((INT8U *)(KeyBoardReportDescriptor),ControlData.wCount);   
  33.         code_transmit((INT8U *)(MouseReportDescriptor),sizeof(MouseReportDescriptor));   
  34.     }   
  35.        
  36.     else  
  37.     {   
  38.            
  39.         stall_ep0();                    //沒有該請求,返回STALL   
  40.   
  41.     }   
  42.     //---------------------------------------------                
  43. }  

B、將control_handler函數中被注銷掉的以下語句取消注釋以複原

 
  1. //else if(type == USB_CLASS_REQUEST)   
  2. //  (*ClassDeviceRequest[req])();           //類請求,如大容量類  

C、找到以下代碼

 
  1. //*************************************************************************   
  2. //USB標准設備請求入口地址指針表   
  3. //*************************************************************************   
  4. code void (*StandardDeviceRequest[])(void) =   
  5. {   
  6.     get_status,   
  7.     clear_feature,   
  8.     reserved,   
  9.     set_feature,   
  10.     reserved,   
  11.     set_address,   
  12.     get_descriptor,   
  13.     reserved,   
  14.     get_configuration,   
  15.     set_configuration,   
  16.     get_interface,   
  17.     set_interface,   
  18.     reserved,   
  19.     reserved,   
  20.     reserved,   
  21.     reserved   
  22. };  

在後面加入

 
  1. //*************************************************************************   
  2. //USB HID設備類请求入口地址指针表   
  3. //*************************************************************************   
  4. code void (*ClassDeviceRequest[])(void) =    
  5. {   
  6.     reserved,   
  7.     get_report,   
  8.     get_idle,   
  9. //  get_protocol,   
  10.     reserved,   
  11.     reserved,   
  12.     reserved,   
  13.     reserved,   
  14.     reserved,   
  15.     reserved,   
  16.     set_report,   
  17.     set_idle,   
  18. //  setprotocol    
  19.     reserved   
  20. };  

D、增加以下代碼

 
  1. //定義USB事件標志變量   
  2. EPPFLAGS bEPPflags;   
  3. 后加入   
  4. unsigned char idle;     //空閑狀態   
  5.   
  6. /****************************************  
  7. ** 函數名稱: void get_report(void)  
  8. ** 功能描述: 讀取報告描述符  
  9. *****************************************/  
  10. void get_report(void)   
  11. {   
  12.                
  13. }   
  14.   
  15. /****************************************  
  16. ** 函數名稱: void set_report(void)  
  17. ** 功能描述: 獲取空閑  
  18. *****************************************/  
  19. void set_report(void)   
  20. {   
  21. }   
  22.   
  23. /****************************************  
  24. ** 函數名稱: void get_idle(void)  
  25. ** 功能描述: 獲取空閑  
  26. *****************************************/  
  27. void get_idle(void)   
  28. {   
  29.     code_transmit(&idle,1);   
  30. }   
  31.   
  32. /****************************************  
  33. ** 函數名稱: void set_idle(void)  
  34. ** 功能描述: 設置空閑  
  35. *****************************************/  
  36. void set_idle(void)   
  37. {   
  38.        
  39.     while(D12_SelectEndpoint(1)&0x01);   
  40.     single_transmit(0, 0);          //發送一個空的數據表示執行完畢   
  41.     idle=ControlData.DeviceRequest.wValue;   
  42. }  

4、修改Chap_9.h

  加入以下代碼

 
  1. #define LSB(x)      ((INT8U)(x))   
  2.   
  3. extern void get_idle(void);   
  4. extern void set_idle(void);   
  5. extern void set_report(void);   
  6. extern void get_report(void);  

第四步、再次編譯程序,將程序寫入主控芯片

  再次怀着激动和不安的心情将我们的Easy USB 51 Programer插入电脑,这次终于实现了我们的USB鼠標了!如图所示,“USB人体学输入设备”已经没有“!”了,而且在“鼠標和其它指针设备”中多了一项“HID-compliant mouse”,这就是我们“设计”的鼠標了。

下載源程序

  但是这个实例还不够生动,因为它并没有鼠標的一点功能,现在我们就来实现部分鼠標的功能。我们可以利用扩展板 EXT-BOARD-A 上的两个按键来模拟鼠標指针的左移和右移,当K1按下鼠標指针左移、K2按下时鼠標指针右移(当然您也可以用它来模拟鼠標左键和鼠標右键)。实现这个功能非常简单,只需修改main函数,其内容如下: 

 
  1. main()   
  2. {      
  3.     unsigned char i = 0;   
  4.     signed char cKeyIn[4];   
  5.        
  6.     if (Init_D12()!=0)                  //初始化D12   
  7.         return;                         //如果初始化不成功,返回   
  8.   
  9.     IT0 = 0;                            //外部中斷0爲電平觸發方式   
  10.        
  11.     EX0 = 1;                            //開外部中斷0   
  12.     PX0 = 0;                            //設置外部中斷0中斷優先級   
  13.     EA  = 1;                                //開80C51總中斷   
  14.        
  15.        
  16.   
  17.     while(1)   
  18.     {   
  19.         usbserve();                     //處理USB事件   
  20.         if(bEPPflags.bits.configuration)   
  21.         {   
  22.             //在這裏添加端點操作代碼                      
  23.             if(bEPPflags.bits.ep2_rxdone )  //主端點接收到數據(從主機發往設備的數據)   
  24.             {   
  25.                 bEPPflags.bits.ep2_rxdone       = 0;   
  26.             }   
  27.                
  28.             K1  = 1;        //P3.5   
  29.             K2  = 1;        //P3.6   
  30.                
  31.             for(i=0;i<100;i++); //延時    
  32.                 
  33.             if(~K1 & K2)    //K1按下   
  34.             {   
  35.                 cKeyIn[0]=0;           
  36.                 cKeyIn[1]=-1;           //鼠標左移   
  37.                 cKeyIn[2]=0;               
  38.                 cKeyIn[3]=0;           
  39.                    
  40.                 D12_WriteEndpoint(5,4,cKeyIn);          //發4個字節到PC機    
  41.             }   
  42.             else if(K1 & ~K2)   //K2按下   
  43.             {   
  44.                 cKeyIn[0]=0;   
  45.                 cKeyIn[1]=1;        //鼠標右移   
  46.                 cKeyIn[2]=0;   
  47.                 cKeyIn[3]=0;   
  48.                    
  49.                 D12_WriteEndpoint(5,4,cKeyIn);          //發4個字節到PC機    
  50.             }   
  51.             /////如果没有扩展板EXT-BOARD-A,可用以下代码段模拟,功能为插入设备后鼠標指针往右移/////   
  52.             //如果有鍵按下   
  53. /*          for(i=0;i<253;i++); //延時  
  54.             cKeyIn[0]=0;  
  55.             cKeyIn[1]=1;        //鼠標右移  
  56.             cKeyIn[2]=0;  
  57.             cKeyIn[3]=0;  
  58.             for(i=0;i<100;i++)  
  59.             {  
  60.                 //if(!bEPPflags.bits.ep2_txdone)  
  61.                     D12_WriteEndpoint(5,4,cKeyIn);          //發4個字節到PC機   
  62.             }  
  63.             */  
  64.             ///////////////////////////////////////////////////////////////////////////////////////////            
  65.            
  66.         }   
  67.     }   
  68. }  

  USB鼠標各个键的定义由报告描述符定义,此实例中的报告描述符描述了4个字節,第一个字節表示按键,第二个字節表示x轴(即鼠標左右移动,0表示不动,正值表示往右移,负值表示往左移),第三个字節表示y轴(即鼠標上下移动,0表示不动,正值表示往下移动,负值表示往上移动),第四个字節表示鼠標滾輪(正值为往上滚动,负值为往下滚动)。

USB鼠標报告各位(字節)用法及含義
字節 用法及含義
0 0 Button1
1 Button2
2 Button3
3 Button4
4 Button5
5~7 Not Used
1 8~15 指針X軸方向位移,相對量(若此值爲1,指針在原來基礎上向右移動一個像素,若爲-1則向左移動一個像素)
2 16~23 指針Y軸方向位移,相對量(若此值爲1,指針在原來基礎上向下移動一個像素,若爲-1則向上移動一個像素)
3 24~31 滾輪

     利用EXT-BOARD-A上的K1和K2键来控制鼠標指针

下載源程序

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