yang_alex 发表于 2018-5-3 12:17

【新版CH554评测】---4.1、USB HID例程学习及验证--描述符

<div class='showpostmsg'> 本帖最后由 yang_alex 于 2018-5-3 12:22 编辑

       USB有很多种插头、插座,也有很多种外设。这篇文章里,主要围绕着CH554评估板所带的USB HID例程展开。在这里CH554评估板做为从设备。

       USB HID类设备属于人机交互设备,如USB鼠标、USB键盘、USB游戏操作杆、USB触摸板、USB轨迹球等等设备。使用HID设备的一个好处是操作系统已经集成了HID类的驱动程序。使用USB HID类设备,开发人员无需开发设备的驱动程序,直接调用API即可完成通信,用户也不用安装USB驱动程序,插入即可识别。所以有很多简单的USB设备喜欢枚举成HID设备,这样就可以不用安装驱动而直接使用。

       我们知道,USB是支持即插即用的。所以,在从设备插入主设备(这里主要是PC)时,主从设备之间是有个交互的,主要内容是从设备告诉主设备:我是谁、我需要什么、我能干什么。但是怎么来说这3件事,是有标准格式要求的,这就是USB技术规范里的“描述符”。

       标准的USB描述符具体又分为设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符这5种描述符。除此之外,还有一些特殊的描述符,例如我们下面会讲到的HID描述符。

       在USB主机访问USB设备的描述符时,USB设备依照设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符顺序将所有描述符传给主机。一个从设备发给主机的内容至少要包含设备描述符、配置描述符和接口描述符,如果USB设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。

       这些描述符之间的关系如下:
       一个USB设备只有一个设备描述符,这个设备描述符确定这个设备有多少种配置,每种配置对应一个配置描述符。配置描述符确定这个配置有多少个接口,每个接口对应一个接口描述符。接口描述符确定这个接口有多少个端点,每个端点对应一个端点描述符。端点描述符定义端点的大小和类型。

       沁恒的代码不是很规整,也不是很完善,看起来有些别扭。建议参考一下Microchip的代码,MCU是软硬结合的产品,好的硬件要和好的软件结合起来才是好产品。

       下面结合CH554评估板所带的USB HID例程展开分析。
设备描述符:(14 个字段,18 Byte)
/*设备描述符*/
UINT8C DevDesc = {0x12,0x01,0x10,0x01,0x00,0x00,0x00,THIS_ENDP0_SIZE,
                      0x31,0x51,0x07,0x20,0x00,0x00,0x00,0x00,
                      0x00,0x01
                     };
   

配置描述符:(8 个字段,9Byte)
UINT8C CfgDesc =
{
0x09,0x02,0x29,0x00,0x01,0x01,0x04,0xA0,0x23,               //配置描述符
};沁恒的代码中把后面几个描述符统一放在了CfgDesc,这里为了描述方便,分开显示了
   

接口描述符:(9 个字段,9Byte)
UINT8C CfgDesc =
{
0x09,0x04,0x00,0x00,0x02,0x03,0x00,0x00,0x05,               //接口描述符
};注意第5个字节0x02,结合下表可知,这个接口下有2个端点
   

端点描述符:(6 个字段,7Byte)
UINT8C CfgDesc =
{
0x07,0x05,0x82,0x03,THIS_ENDP0_SIZE,0x00,0x18,            //端点描述符
0x07,0x05,0x02,0x03,THIS_ENDP0_SIZE,0x00,0x18,            //端点描述符
};结合上面接口描述符中的描述,这个接口下有2个端点
   

字符串描述符:(3 个字段,长度没有限制)
本例中没有使用字符串描述符
   

HID描述符:(10 个字段,12Byte)
UINT8C CfgDesc =
{
0x09,0x21,0x00,0x01,0x00,0x01,0x22,0x22,0x00,               //HID类描述符
};注意第6个字节0x01,第7个字节0x22,第8、9个字节0x22,0x00,结合下表可知,HID描述符附加一个报告描述符,报告描述符的长度是0x0022,即34个字节。这部分有点疑问:标准中说10个字段,12字节。但沁恒的代码中是9个字节,感觉是把最后面2个字段,3个字节省掉了。
(补充:后来突然明白了,表格里说的很明白,最后面2个字段,3个字节是在超出1个附加报告描述符时才会有,本例中只有1个附加报告描述符,所以就省掉了:lol)
   
附加报告描述符:
      报告描述符: HID设备的报告描述符比较复杂也比较难理解。它以item形式排列组合而成,无固定长度,用户可以自定义长度以及每一bit的含义。HID报告描述符已经不是简简单单地描述某个值对应某个固定意义了,它能够组合出很多种情况,并且需要PC上的HID驱动程序提供parser解释器来对描述的设备情形进行重新解释,从而组合生成出本HID硬件设备独特的数据流格式。USB协会提供了一个HID描述符编辑工具HIDDescrioptor Tool,用它可以方便生成报告描述符。


/*HID类报表描述符*/
UINT8C HIDRepDesc[ ] =
{
    0x06, 0x00,0xff,
    0x09, 0x01,
    0xa1, 0x01,                                                   //集合开始
    0x09, 0x02,                                                   //Usage Page用法
    0x15, 0x00,                                                   //LogicalMinimun
    0x26, 0x00,0xff,                                              //LogicalMaximun
    0x75, 0x08,                                                   //Report Size
    0x95, THIS_ENDP0_SIZE,                                        //Report Counet
    0x81, 0x06,                                                   //Input
    0x09, 0x02,                                                   //Usage Page用法
    0x15, 0x00,                                                   //LogicalMinimun
    0x26, 0x00,0xff,                                              //LogicalMaximun
    0x75, 0x08,                                                   //Report Size
    0x95, THIS_ENDP0_SIZE,                                        //Report Counet
    0x91, 0x06,                                                   //Output
    0xC0
};从代码中可以看出,这个报告描述符像前面HID描述符中所说,有34个字节的内容。

到此,描述符分析完。下面一贴分析USB程序框架。


此内容由EEWORLD论坛网友yang_alex原创,如需转载或用于商业用途需征得作者同意并注明出处






</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

cruelfox 发表于 2018-5-3 12:24

用字符数组来写描述符,省事,就是比用 struct 描述容易出错。

yang_alex 发表于 2018-5-3 13:14

cruelfox 发表于 2018-5-3 12:24
用字符数组来写描述符,省事,就是比用 struct 描述容易出错。

对。

不过即使用数组来写描述符只要格式清晰,描述准确也可以接受。沁恒用一个 CfgDesc的方式就有些别扭了。

英尚微电子 发表于 2018-5-3 15:50

页: [1]
查看完整版本: 【新版CH554评测】---4.1、USB HID例程学习及验证--描述符