网站导航:首页开源项目 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