您现在的位置: USB开发网 > USB开源项目 > Easy USB 51 Programer Plus
- Easy USB 51 Programer Plus

自定义USB HID设备—固件程序开发

------分隔线----------------------------

  经常看到一些USB设备采用HID设备类,这种设备使用时不需要另外安装驱动程序,使用起来非常方便,如我自己用的PIC单片机在线调试工具PIC KIT3和C8051F系列单片机在线调试工具U-EC5都是HID设备,还有日常生活中常用的读卡机、指纹考勤机等都经常设计成USB HID接口,HID设备直接插上电脑就可以使用,在后面章节中介绍的超酷实例—51系列单片机编程器 也是基于HID设备类的。

  由于HID的数据包可以由报告描述符来定义,所以可以方便地由设计人员自己定义适合项目所要的数据包格式,这样就可以利用HID设备类实现大多数数据通讯的应用需求,更重要的一点是操作系统通常都自带了HID设备驱动程序,用户使用时不需要插入驱动光盘来安装驱动程序,使用起来非常方便。从这一节开始我们来介绍如何实现自定义USB HID设备类,一般自定义USB HID设备类一般都有PC端用户应用程序,所以我们还会讲到如果编写PC端应用程序来与自定义HID设备通讯,这一节先介绍如何编写自定义USB HID设备固件。

  《USB鼠标实例》一节已经通过实验证明HID接口描述符中bInterfaceProtocol字段的值并不影响设备类型,而且查看协议得知只有1和2两种取值有具体含义,影响设备类型的是报告描述符,报告描述符的用途页(USAGE_PAGE)有厂商自定义(Vendor Defined Page)的选项,所以要实现自定义USB HID设备类,只需要在报告描述符里定义厂商自定义的描述符就可以了,我们在上一节实例的基础上修改报告描述符,修改内容如下:

  1. code char MouseReportDescriptor[29] = {      
  2.     0x06,0x00,0xFF,             //USAGE_PAGE (Vendor Defined Page 1)       
  3.     0x09,0x01,              //USAGE (Vendor Usage 1)       
  4.     0xA1,0x01,              //COLLECTION (Application)       
  5.      
  6.     0x19,0x01,              //(Vendor Usage 1)       
  7.     0x29,0x08,              //(Vendor Usage 1)       
  8.     0x15,0x00,              //LOGICAL_MINIMUM (0)       
  9.     0x26,0xFF,0x00,             //LOGICAL_MAXIMUM (255)       
  10.     0x75,0x08,              //REPORT_SIZE (8)       
  11.     0x95,0x40,              //REPORT_COUNT (64)       
  12.     0x81,0x02,              //INPUT (Data,Var,Abs)       
  13.      
  14.     0x19,0x01,              //(Vendor Usage 1)       
  15.     0x29,0x08,              //(Vendor Usage 1)       
  16.     0x91,0x02,              //OUTPUT (Data,Var,Abs)       
  17.      
  18.     0xC0                    // END_COLLECTION      
  19. };     

  以上报告描述符只定义了一个报告(数据包,包括输入和输出),所以没有报告ID,这个报告由64个字节组成。

  但是这个自定义USB HID设备什么功能也没有,下面我们简单地实现一个功能:数据包前8个字节为命令(主机到设备)或状态(设备到主机),如果收到前八个字节是字符串“_SET_LED”,那后面紧跟的一个字节代表8个LED状态(每位代表一个LED的状态),如果收到的前八个字节是字符串“GET_TEXT”则代表要求设备返回一个字符串,此时设备应返回64个字节,前面八个字节仍为“GET_TEXT”代表返回LED状态,后面是返回的字符,以NULL结尾;如果设备返回数据包前八个字节为“KEY_STAT”,则代表设备返回按键状态,紧跟后面的一个字节低两位分别代表K1和K2的状态。继续修改main函数,内容如下:

 

  1. main()  
  2. {  
  3.     unsigned char xdata ucTxBuffer[64]; //发送缓冲区   
  4.     if (Init_D12()!=0)      //初始化D12  
  5.         return;         //如果初始化不成功,返回  
  6.  
  7.     IT0 = 0;            //外部中断0为电平触发方式  
  8.       
  9.     EX0 = 1;            //开外部中断0  
  10.     PX0 = 0;            //设置外部中断0中断优先级  
  11.     EA = 1;             //开80C51总中断  
  12.       
  13.     bKey1Down   = 0;  
  14.     bKey2Down   = 0;  
  15.  
  16.     while(1)  
  17.     {  
  18.         usbserve();     //处理USB事件  
  19.         if(bEPPflags.bits.configuration)      
  20.         {      
  21.             //在这里添加端点操作代码      
  22.             //请参考光盘提供的示例   
  23.               
  24.             if(bEPPflags.bits.ep2_rxdone )  //主端点接收到数据(从主机发往设备的数据)      
  25.             {      
  26.                 bEPPflags.bits.ep2_rxdone       = 0;          
  27.                   
  28.                 //判断是否是 _SET_LED 命令(EpBuf的前8个字节为”_SET_LED“)           
  29.                 if(strncmp("_SET_LED",EpBuf,8)==0)    
  30.                 {                     
  31.                     //设定LED状态  
  32.                     P0  = EpBuf[8];  
  33.                 }  
  34.                   
  35.                 //判断是否是 GET_TEXT 命令(EpBuf的前8个字节为”GET_TEXT“)           
  36.                 if(strncmp("GET_TEXT",EpBuf,8)==0)    
  37.                 {  
  38.                     //返回一些字符串,前八个字节为“GET_TEXT”,后面是返回的字符串  
  39.                     strcpy(ucTxBuffer,"GET_TEXT:Easy usb 51 programer plus - usb.baiheee.com");                   
  40.                     D12_WriteEndpoint(5,EP2_PACKET_SIZE,EpBuf);    //立即将收到的64个字节发送到PC机  
  41.                 }                     
  42.             }     
  43.               
  44.               
  45.             //按键服务(为了演示方便,未使用按键消抖)  
  46.             if(~K1 & K2 & ~bKey1Down)    //K1按下  
  47.             {  
  48.                 bKey1Down   = 1;  
  49.                 strcpy(ucTxBuffer,"KEY_STAT");  
  50.                 ucTxBuffer[8]   = 0x01;  
  51.                 D12_WriteEndpoint(5,EP2_PACKET_SIZE,EpBuf);    //立即将收到的64个字节发送到PC机  
  52.             }  
  53.             else if(K1 & ~K2 & ~bKey2Down)    //K2按下  
  54.             {  
  55.                 bKey2Down   = 1;  
  56.                 strcpy(ucTxBuffer,"KEY_STAT");  
  57.                 ucTxBuffer[8]   = 0x02;  
  58.                 D12_WriteEndpoint(5,EP2_PACKET_SIZE,EpBuf);    //立即将收到的64个字节发送到PC机  
  59.             }  
  60.               
  61.             if(K1)  //K1未按下  
  62.             {  
  63.                 bKey1Down   = 0;      
  64.             }  
  65.             if(K2)  //K2未按下  
  66.             {  
  67.                 bKey2Down   = 0;      
  68.             }  
  69.         }    
  70.     }  

 

 

自定义USB HID设备类(Firmware code)

 

测试:

  由于目前还没有编写上位机应用程序,所以只能用常用的bus hound工具来测试,bus hound可以抓取USB设备枚举及数据交换过程中的数据包,并可向指定端点发送数据包。首先下载bus hound,我这里使用的是5.0版本。

A、编译并烧录上面的程序,然后打开BUS HOUND,点“Settings”按钮切换到设置页,将“Max Phase”的值设为64并点“Apply”按钮,这样BUS HOUND才能监控最多64个字节的数据流。 

自定义USB HID设备类-BUS HOUND 界面设置 - buffer设置
图1
 
B、插上烧好程序后的设备,点“Devices”按钮切换到Devices页,选中我们刚插入的硬件(要选“USB Root Hub”分支下的那个设备)
 
自定义USB HID设备类-BUS HOUND 界面设置 - 选择设备
图2
 
C、点“Capture”按钮,切换到Capture页,确保右下角“Run”按钮被选中,这时分别按扩展板上的K1键和K2键,结果BUS HOUND捕捉到了一些数据,如下所示,前八个字符应该是“KEY_STAT”,第9个字符的低两位代表K1和K2状态,下图所示为K1按下时捕捉到的数据,其中Phase列的“DI”代表输入数据(设备到主机)
 
自定义USB HID设备类-BUS HOUND 界面设置 - 按键测试
 图3
 
D、点“Devices”按钮,切换到“Devices”页,再次选中我们的“USB人体学输入设备”,如图2所示,再点右下角的“Send Commands”按钮。  然后出现下面所示画面,选中“Endpoint”为2,“Direction”为Out的那项,“Data Length”的值填64,代表发送64个字节的数据,发送的数据前八个字节填“_SET_LED”,第九个字节填:AA,即二进制的10101010,意思是点这D1,D3,D5,D7, 然后点左上角的“Run”按钮,这只看到扩展板上的LED相就的灯被点这了(图5)。
 
自定义USB HID设备类-BUS HOUND 界面设置 - 向输出端点发数据
 
图4
 
自定义USB HID设备类-控制LED效果
 
图5
 E、重新设备前八字节为字符串“GET_TEXT”,然后点“Run”按钮,再切换到“Capture”页,可以看到返回了一些数据,前八字节仍为“GET_TEXT”,后面是:Easy usb 51 programer plus - usb.baiheee.com 。
 
自定义USB HID设备类-BUS HOUND 界面设置 - 捕捉到返回数据
 
图6

 

------分隔线----------------------------
联系我们
  • Q Q: 1148374829 点击这里给我发消息
  • 旺旺:jhoneqhsieh 点击这里给我发消息
  • 电话:(0)15923141204
  • 淘宝网店