历史上的今天
返回首页

历史上的今天

今天是:2025年03月24日(星期一)

正在发生

2019年03月24日 | STM32 自定义HID USB设备的实现

2019-03-24 来源:eefocus

最近需要使用STM32开发一个设备通过HID协议与主机通信,于是开始学习USB,发现USB这个体系实在太庞大了,直接看USB的例程根本看不懂,完全找不到突破口,最后在网上找到一本不错的书《圈圈教你玩USB》,这本书能够很好地带你入门。枚举过程,请求,令牌,数据包,端点,描述符,这些知识都讲的很清楚,只有清楚了这些,再去看代码就能明白是怎么回事了。


接下来总结一个我个人的理解:对于HID设备,STM32有例程,但是怎么修改成符合自己要求的HID设备呢?首先,HID设备必需有报告描述符,报告描述符描述的是数据的长度以及用途,所以最重要的就是修改报告描述符,如我现在只是需要用来传数据,一次最大16字节长度;修改后的报告描述符如下:


const u8 CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =

  {   

    //这是一个全局(bType为1)条目,将用途页选择为普通桌面Generic Desktop Page。

 

 //后面跟1字节数据(bSize为1),后面的字节数就不注释了,自己根据bSize来判断。

 

 0x05, 0x01, // USAGE_PAGE (Generic Desktop)

 

 

 

 //这是一个局部(bType为2)条目,用途选择为0x00。在普通桌面页中,

 

 //该用途是未定义的,如果使用该用途来开集合,那么系统将不会把它

 

 //当作标准系统设备,从而就成了一个用户自定义的HID设备。

 

 0x09, 0x00, // USAGE (0)

 

 

 

 //这是一个主条目(bType为0)条目,开集合,后面跟的数据0x01表示

 

 //该集合是一个应用集合。它的性质在前面由用途页和用途定义为

 

 //用户自定义。

 

 0xa1, 0x01, // COLLECTION (Application)

 

 

 

 //这是一个全局条目,说明逻辑值最小值为0。

 

 0x15, 0x00, //     LOGICAL_MINIMUM (0)

 

 

 

 //这是一个全局条目,说明逻辑值最大为255。

 

 0x25, 0xff, //     LOGICAL_MAXIMUM (255)

 

 

 

 //这是一个局部条目,说明用途的最小值为1。

 

 0x19, 0x01, //     USAGE_MINIMUM (1)

 

 

 

 //这是一个局部条目,说明用途的最大值8。

 

 0x29, 0x08, //     USAGE_MAXIMUM (8) 

 

 

 

 //这是一个全局条目,说明数据域的数量为16个。

 

 0x95, 0x10, //     REPORT_COUNT (16)

 

 

 

 //这是一个全局条目,说明每个数据域的长度为8bit,即1字节。

 

 0x75, 0x08, //     REPORT_SIZE (8)

 

 

 

 //这是一个主条目,说明有16个长度为8bit的数据域做为输入。

 

 0x81, 0x02, //     INPUT (Data,Var,Abs)

 

 

 

 //下面这个主条目用来关闭前面的集合。bSize为0,所以后面没数据。

 

 0xc0        // END_COLLECTION

  }; /* CustomHID_ReportDescriptor */

另外,别忘了去端点描述符修改数据长度


/* USB Configuration Descriptor */

/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */

const u8 CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] =

  {

    0x09, /* bLength: Configuation Descriptor size */

    USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */

    CUSTOMHID_SIZ_CONFIG_DESC,

    /* wTotalLength: Bytes returned */

    0x00,

    0x01,         /* bNumInterfaces: 1 interface */

    0x01,         /* bConfigurationValue: Configuration value */

    0x00,         /* iConfiguration: Index of string descriptor describing

                                 the configuration*/

    0xC0,         /* bmAttributes: Bus powered */

    0x32,         /* MaxPower 100 mA: this current is used for detecting Vbus */

 

    /************** Descriptor of Custom HID interface ****************/

    /* 09 */

    0x09,         /* bLength: Interface Descriptor size */

    USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */

    0x00,         /* bInterfaceNumber: Number of Interface */

    0x00,         /* bAlternateSetting: Alternate setting */

    0x02,         /* bNumEndpoints */

    0x03,         /* bInterfaceClass: HID */

    0x00,         /* bInterfaceSubClass : 1=BOOT, 0=no boot */

    0x00,         /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */

    0,            /* iInterface: Index of string descriptor */

    /******************** Descriptor of Custom HID HID ********************/

    /* 18 */

    0x09,         /* bLength: HID Descriptor size */

    HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */

    0x10,         /* bcdHID: HID Class Spec release number */

    0x01,

    0x00,         /* bCountryCode: Hardware target country */

    0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */

    0x22,         /* bDescriptorType */

    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */

    0x00,

    /******************** Descriptor of Custom HID endpoints ******************/

    /* 27 */

    0x07,          /* bLength: Endpoint Descriptor size */

    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */

 

    0x81,          /* bEndpointAddress: Endpoint Address (IN) */

    0x03,          /* bmAttributes: Interrupt endpoint */

    0x10,          /* wMaxPacketSize: 16 Bytes max */

    0x00,

    0x20,          /* bInterval: Polling Interval (32 ms) */

    /* 34 */

   

    0x07, /* bLength: Endpoint Descriptor size */

    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */

/* Endpoint descriptor type */

    0x01, /* bEndpointAddress: */

/* Endpoint Address (OUT) */

    0x03, /* bmAttributes: Interrupt endpoint */

    0x10, /* wMaxPacketSize: 16 Bytes max  */

    0x00,

    0x20, /* bInterval: Polling Interval (20 ms) */

    /* 41 */

  }

  ; 

剩下的就根据自己需要去修改数据OUT处理和数据IN处理函数,来进行自己的数据处理,从而实现自定义HID。


 


当然使用HID进行数据传输并不是好的办法,USB有专门用于数据传输的协议,CDC,想要实现肯定是有办法的,但是因为我主机要求使用HID通信,我也只能使用HID来做了,什么CDC等要用到的时候再研究了。


推荐阅读

史海拾趣

Bergquist Company公司的发展小趣事

在60年代,Bergquist Company作为一家私人拥有的美国公司,在明尼苏达州的一个小城市诞生。创立初期,公司面临着资金短缺、市场竞争激烈等诸多困难。然而,创始人凭借着对导热材料行业的深刻洞察和坚定信念,带领公司一步步走过了创业初期的艰难岁月。他们不断研发新产品,提升产品质量,逐渐在市场上获得了一席之地。

Centellax Inc公司的发展小趣事

Centellax Inc公司自成立以来,一直致力于电子通信技术的研发与创新。在成立初期,公司凭借其独特的测试测量技术,在光通信行业中崭露头角。随着技术的不断迭代和市场的扩大,Centellax逐渐积累了大量的专利和知识产权,为公司的长期发展奠定了坚实的基础。

在技术创新方面,Centellax不断投入研发资源,推出了一系列高性能的测试测量设备。这些设备不仅满足了客户对高速器件深入分析的需求,还提升了公司在行业内的竞争力。同时,Centellax还积极与高校、研究机构等合作,共同推动电子通信技术的进步。

Alpha (Taiwan)公司的发展小趣事

面对全球环保意识的日益增强,Alpha (Taiwan)公司积极响应号召,致力于绿色电子产品的研发和生产。公司投入大量资金研发环保材料和技术,成功推出了一系列绿色环保电子产品。这些产品不仅具有优异的性能,而且在使用过程中对环境的影响较小,符合现代社会的环保理念。此外,公司还积极参与环保公益活动,宣传环保知识,推动电子行业的绿色发展。

General Electric Solid State公司的发展小趣事

随着全球电子市场的不断扩大,Alpha (Taiwan)公司积极寻求国际合作,拓宽市场渠道。公司与多家国际知名电子企业建立了战略合作关系,共同研发新产品,开拓新市场。此外,公司还积极参加国际电子展会,展示公司的最新技术和产品,吸引更多的潜在客户。这些国际合作的开展,不仅提升了公司的国际影响力,也为公司的长远发展注入了新的动力。

FORMOSA公司的发展小趣事

在半导体技术日新月异的时代,一家名为“FORMOSA半导体科技”的公司凭借其在先进制程技术上的突破,迅速在行业内崭露头角。该公司专注于研发和生产高性能的处理器和存储器芯片,为智能手机、数据中心等高端应用提供核心动力。通过持续的研发投入和与全球顶尖科技公司的合作,FORMOSA半导体科技成功打破了多项技术壁垒,其产品在市场上赢得了广泛赞誉。公司还积极响应绿色环保的号召,推出了一系列低功耗、高效率的半导体解决方案,为可持续发展贡献力量。

Gowanda Electronics公司的发展小趣事

在台湾,一家名为“FORMOSA电子元件制造厂”的公司,起初是一家小型电阻器生产商,专注于为本地电子制造商提供基础元件。随着个人电脑和消费电子市场的蓬勃发展,该公司敏锐地捕捉到市场需求,开始投资研发高精度、低成本的电子元件。通过不断的技术创新和质量控制,FORMOSA电子元件逐渐在国际市场上获得认可,成为多家知名电子产品制造商的供应商。公司还积极拓展海外市场,在欧洲和北美设立分支机构,进一步巩固了其在全球电子元件市场的地位。

问答坊 | AI 解惑

频谱可用性对移动电视解决方案的影响 (转贴)

在移动运营商寻求非语音业务收入增长时,终端用户对高级多媒体应用范围和业务的需求也在飞速增长。那些期望从其他来源获取收入增长的运营商在可下载游戏、应用程序和音轨等方面已取得成功。移动电视提供了一个潜在的盈利业务,这是当前很多运营商考 ...…

查看全部问答>

列车电气规范

可能需要的朋友会用到 en50126…

查看全部问答>

这个时钟走时误差太大了

刚做好一个时钟(还要谢谢帮我修改程序的那些热心的朋友们),装好运行后发现每走一小时就要快5分钟左右,一天下来就差不多快了两小时。12MHz的石英晶振换过了,那两只电容也由原来的33P换到22P,再换到12P还是不行。我把电路原理图和工程文件一起 ...…

查看全部问答>

小弟出入嵌入式,希望前辈给点指点

如题 谢谢啦 本人另建QQ高级群一个 92208632 嵌入式 大家可以互相学习…

查看全部问答>

uCGUI中文手册

μC/GUI μC/GUI 是一种用于嵌入式应用的图形支持软件。它被设计用于为任何使用一个图形LCD的应用提供一个有效的不依赖于处理器和LCD 控制器的图形用户接口。它能工作于单任务或多任务的系统环境下。μC/GUI 适用于使用任何LCD 控制和CPU 的任何尺 ...…

查看全部问答>

如何使用2440GPIO模仿SPI口通讯

大家好。现在想使用2440的GPIO模拟SPI口通讯,主控制器是2440主板,从器件是LCD屏驱动器 2440主频工作在400Mhz LCD屏驱动器SPI口频率不超过20Mhz。 现在发现GPIO输出频率可能过高 使用2440的GPIO模拟SPI口通讯,GPIO的频率要怎么控制呢?会不会 ...…

查看全部问答>

西门子MC39I插卡无法启动

我的MC39I不插卡时能启动,插卡后启动不到5秒就自动关闭了,有哪位大侠知道是什么原因,是电源有问题吗,请高手指点,最好能提供一个电源解决方案,另外,我的模块直接接的SIM卡,SIM卡各引脚之间没有接电容,或电感,这有影响吗?…

查看全部问答>

用编程器读取出来的数据怎么读解??

兴趣学者,请教大家一个问题,用编程器从芯片里读取出来的数据都是16进制的,ASCII码显示是很乱,我该用什么方法读解??谢谢大家…

查看全部问答>

新手问题。EVC新建一个工程不能选CPU类型?

启动EVC新建一个工程不能选CPU类型呢?所有的CPU类型全部是灰色的?在Tools->confure platform manage下能手动启动模拟器,。。。。。另外,点Tools->Options->Directories程序就异常退出了?这是为什么?…

查看全部问答>

寄存器如何正确映射到虚拟内存里?

我写了一个读写iic的程序.对寄存器进行操作的时候出错了. 程序头 #define rGPECON    (*(volatile unsigned *)0x56000040) //Port E control #define rGPEDAT    (*(volatile unsigned *)0x56000044) //Port E data #def ...…

查看全部问答>