STM32配置USB组合设备

STM32配置USB组合设备

有个比喻描述的特别好

说到USB复合设备就不得不说说USB的枚举过程,也就是USB插入后主机的一系列动作。当然我们这里是不会用很专业的术语来说明的,相信如果你是开发者,必然已经了如指掌,如果你是使用者,更是不愿看到太多的专业术语的。

我把USB的枚举比作一个自我介绍,在插入后主机会询问USB设备的属性,而设备则像自我介绍一样告诉主机自己的“名字”,“年龄”,“证件号”,“母语”等等。主机也是根据这些来区分插入的设备的。

因此,我们可以做个假设是不是修改相应的身份信息(也就是描述符)就可以实现复合设备了呢?答案是肯定的,但是具体要修改那些描述符就需要来分析一下了。

因此想要实现USB复合,需要解决的最大的一个问题就是USB描述符!


1. 修改USB组合设备描述符之“设备描述符”

  • 组合设备需要对设备描述符进行修改,见下图
    在这里插入图片描述
    修改设备描述符,描述设备为综合设备,对应修改usbd_desc.c文件内的
/** USB standard device descriptor. USB设备描述符 */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
  0x12,                       /*bLength */
  USB_DESC_TYPE_DEVICE,       /*bDescriptorType 描述符编号0x01 */
  0x00,                       /*bcdUSB 版本2.0 */
  0x02,
  0xEF,                       /*bDeviceClass 综合设备 */
  0x02,                       /*bDeviceSubClass*/
  0x01,                       /*bDeviceProtocol*/
  USB_MAX_EP0_SIZE,           /*bMaxPacketSize 端点0大小为64字节 */
  LOBYTE(USBD_VID),           /*idVendor  厂家ID */
  HIBYTE(USBD_VID),           /*idVendor*/
  LOBYTE(USBD_PID_FS),        /*idProduct 产品ID */
  HIBYTE(USBD_PID_FS),        /*idProduct*/
  0x00,                       /*bcdDevice rel. 2.00版本*/
  0x02,
  USBD_IDX_MFC_STR,           /*Index of manufacturer string 厂商字符串索引值 0x01 */
  USBD_IDX_PRODUCT_STR,       /*Index of product string 产品字符串索引值 0x02 */
  USBD_IDX_SERIAL_STR,        /*Index of serial number string 设备序列号字符串索引值 0x03 */
  USBD_MAX_NUM_CONFIGURATION  /*bNumConfigurations 该设备所具有的配置数 0x01 */
};

2. 修改USB组合设备描述符之“配置描述符、接口描述符、端点描述符”

就是把多个设备的配置描述符、接口描述符、端点描述符拼接在一起,设备之间加入一个IAD描述符分隔开来,同时每个接口描述符的接口编号需要修改,下面是我弄的HID+CDC的配置描述符、接口描述符、端点描述符,仅供参考


/* USB composite device Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN uint8_t USBD_Composite_CfgFSDesc[USBD_COMPOSITE_DESC_SIZE]  __ALIGN_END =
{
  /* 配置描述符 */
  0x09,   /* bLength: Configuation Descriptor size */
  USB_DESC_TYPE_CONFIGURATION,   /* bDescriptorType: Configuration */
  USBD_COMPOSITE_DESC_SIZE,  
  0x00,
  USBD_MAX_NUM_INTERFACES ,  /* bNumInterfaces: */
  0x01,   /* bConfigurationValue: 0 配置的值 */
  0x00,   /* iConfiguration: 00 字符串索引 */
  0x80,   /* bmAttributes:no-bus powered and Dissupport Remote Wake-up*/
  0x32,   /* MaxPower 100 mA  */


  /****************************HID************************************/
  /* Interface Association Descriptor */
  USBD_IAD_DESC_SIZE,                        // bLength IAD描述符大小
  USBD_IAD_DESCRIPTOR_TYPE,                  // bDescriptorType IAD描述符类型
  0x00,                                      // bFirstInterface 接口描述符是在总的配置描述符中的第几个从0开始数
  0x01,                                      // bInterfaceCount 接口描述符数量
  0x03,                                      // bFunctionClass  设备符中的bDeviceClass
  0x00,                                      // bFunctionSubClass  设备符中的bDeviceSubClass
  0x00,                                      // bInterfaceProtocol 设备符中的bDeviceProtocol
  0x00,

  /********************  HID interface ********************/
  /************** Descriptor of Custom HID interface ****************/
  /* 09 */
  0x09,                   /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
  0x00,                   /*bInterfaceNumber: Number of Interface 接口编号 0 */
  0x00,                   /*bAlternateSetting: Alternate setting  备用接口 */
  0x01,                   /*bNumEndpoints 使用的端点数 1 */
  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 ********************/
  /* 18 */
  0x09,                   /*bLength: HID Descriptor size*/
  HID_DESCRIPTOR_TYPE,    /*bDescriptorType: HID*/
  0x00,                   /*bcdHID: HID Class Spec release number*/
  0x01,
  0x00,                   /*bCountryCode: Hardware target country*/
  0x01,                   /*bNumDescriptors: Number of HID class descriptors to follow*/
  0x22,                   /*bDescriptorType*/
  HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /******************** Descriptor of TouchScreen endpoint ********************/
  /* 27 */
  0x07,                   /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/

  HID_EPIN_ADDR,          /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,                   /*bmAttributes: Interrupt endpoint*/
  HID_EPIN_SIZE,          /*wMaxPacketSize: 16 Byte max */
  0x00,
  HID_FS_BINTERVAL,       /*bInterval: Polling Interval */
  /* 34 */
  
  /****************************CDC************************************/
  /* IAD描述符 */
  /* Interface Association Descriptor */
  USBD_IAD_DESC_SIZE,               // bLength
  USBD_IAD_DESCRIPTOR_TYPE,         // bDescriptorType
  0x01,                             // bFirstInterface 接口描述符是在总的配置描述符中的第几个从0开始数 1
  0x02,                             // bInterfaceCount 接口描述符数量 2
  0x02,                             // bFunctionClass     CDC Control
  0x02,                             // bFunctionSubClass  Abstract Control Model
  0x01,                             // bInterfaceProtocol  AT Commands: V.250 etc
  0x00,                             // iFunction
  
  /* CDC命令接口描述符 */
  /*Interface Descriptor */
  0x09,   /* bLength: Interface Descriptor size 长度 */
  USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface 接口编号0x04 */
  /* Interface descriptor type */
  0x01,   /* bInterfaceNumber: Number of Interface 接口编号,第一个接口编号为1 */
  0x00,   /* bAlternateSetting: Alternate setting 接口备用编号 0 */
  0x01,   /* bNumEndpoints: One endpoints used 非0端点的数目 1 cdc接口只使用了一个中断输入端点 */
  0x02,   /* bInterfaceClass: Communication Interface Class 接口所使用的类0x02 */
  0x02,   /* bInterfaceSubClass: Abstract Control Model 接口所使用的子类0x02 */
  0x01,   /* bInterfaceProtocol: Common AT commands 使用AT命令协议 */
  0x00,   /* iInterface: 接口字符串索引值 0表示没有 */

  /* 类特殊接口描述符--功能描述符 用来描述接口的功能 */
  /*Header Functional Descriptor*/
  0x05,   /* bLength: Endpoint Descriptor size 描述符长度为5字节 */
  0x24,   /* bDescriptorType: CS_INTERFACE 描述符类型为类特殊接口CS_INTERFACE*/
  0x00,   /* bDescriptorSubtype: Header Func Desc 子类为 Header Func Desc,编号0x00 */
  0x10,   /* bcdCDC: spec release number CDC版本 */
  0x01,

  /*Call Management Functional Descriptor*/
  0x05,   /* bFunctionLength */
  0x24,   /* bDescriptorType: CS_INTERFACE 描述符类型为类特殊接口CS_INTERFACE*/
  0x01,   /* bDescriptorSubtype: Call Management Func Desc 子类为Call Management Func Desc 编号0x01*/
  0x00,   /* bmCapabilities: D0+D1 设备自己不管理call management */
  0x01,   /* bDataInterface: 1 有一个数据类接口用作call management */

  /*ACM Functional Descriptor*/
  0x04,   /* bFunctionLength */
  0x24,   /* bDescriptorType: CS_INTERFACE 描述符类型为类特殊接口CS_INTERFACE*/
  0x02,   /* bDescriptorSubtype: Abstract Control Management desc 子类为Abstract Control Management desc编号0x02*/
  0x02,   /* bmCapabilities 支持Set_Control_Line_State、Get_Line_Coding请求和Serial_State通知*/

  /*Union Functional Descriptor*/
  0x05,   /* bFunctionLength */
  0x24,   /* bDescriptorType: CS_INTERFACE 描述符类型为类特殊接口CS_INTERFACE */
  0x06,   /* bDescriptorSubtype: Union func desc 子类为Union func desc 编号0x06*/
  0x01,   /* bMasterInterface: Communication class interface 编号为1的CDC接口 */
  0x02,   /* bSlaveInterface0: Data Class Interface 编号为2的数据类接口 */

  /*Endpoint 2 Descriptor*/
  0x07,                           /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_ENDPOINT,   			/* bDescriptorType: Endpoint */
  CDC_CMD_EP,                     /* bEndpointAddress */
  0x03,                           /* bmAttributes: Interrupt */
  LOBYTE(CDC_CMD_PACKET_SIZE),    /* wMaxPacketSize: */
  HIBYTE(CDC_CMD_PACKET_SIZE),
  CDC_FS_BINTERVAL,                           /* bInterval: */
  /*---------------------------------------------------------------------------*/

	/* 数据类接口的接口描述符 */
  /*Data class interface descriptor*/
  0x09,   /* bLength: Endpoint Descriptor size 接口描述符长度9字节*/
  USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: 接口描述符的编号0x04*/
  0x02,   /* bInterfaceNumber: Number of Interface 接口的编号为2*/
  0x00,   /* bAlternateSetting: Alternate setting 该接口的备用编号为0 */
  0x02,   /* bNumEndpoints: Two endpoints used 非0端点的数据 设备需要使用一对批量端点,设置为2*/
  0x0A,   /* bInterfaceClass: CDC 该接口所使用的类 数据类接口代码为0x0A */
  0x00,   /* bInterfaceSubClass: 接口所使用的子类为0*/
  0x00,   /* bInterfaceProtocol: 接口所使用的协议为0*/
  0x00,   /* iInterface:  接口的字符串索引值,0表示没有*/

	/* 输出端点的端点描述符 */
  /*Endpoint OUT Descriptor*/
  0x07,   /* bLength: Endpoint Descriptor size 端点描述符长度7字节 */
  USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType: Endpoint 端点描述符编号为0x05 */
  CDC_OUT_EP,                           /* bEndpointAddress 端点的地址0x02 D7为方向*/
  0x02,                                 /* bmAttributes: Bulk 批量传输*/
  LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),  /* wMaxPacketSize: 端点的最大包长 512字节*/
  HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
  0x00,                                 /* bInterval: ignore for Bulk transfer 端点查询时间,对批量端点无效 */

	/* 输入端点的端点描述符 */
  /*Endpoint IN Descriptor*/
  0x07,   /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_ENDPOINT,               /* bDescriptorType: Endpoint 端点描述符编号为0x05*/
  CDC_IN_EP,                            /* bEndpointAddress 端点的地址0x82 D7为方向*/
  0x02,                                 /* bmAttributes: Bulk 批量传输*/
  LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),  /* wMaxPacketSize: 端点的最大包长 512字节*/
  HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
  0x00                                  /* bInterval: ignore for Bulk transfer 端点查询时间,对批量端点无效*/
};

3. 修改USB外设所支持的最大接口数

因为组合设备肯定是使用的多个接口,肯定不止1个,所以需要配置stm32硬件所支持的接口数大于或等于实际使用的接口数,对应修改usbd_conf.h内的
#define USBD_MAX_NUM_INTERFACES 3

4. 修改每个端点的地址

组合设备如何区分数据是发给谁的呢,肯定是不同的设备有不同的接口了,因此我们需要整理每一个设备的端点地址,不能冲突!!!注意的是,端点地址的第七位表示的是方向!

5. 修改PID和VID

为什么要改,请看下面我踩过的坑!


  • USB组合设备之大坑

  • 1号大坑
  • 确认描述符没有问题,但是USB插上电脑之后依旧只能识别一个设备,记得修改VID和PID,卸载驱动,重新插拔,由于USB是通过PID和VID来加载驱动的,如果我们继续使用stm32虚拟串口对应的VID1155PID22336,则会自动加载虚拟串口的驱动,使得电脑根据驱动,只会去加载一个设备,修改VID为1156,PID为22339之后重新卸载驱动,重新插拔,之后便可以识别到两个设备!!!
  • 2号大坑
  • 修改了VID和PID之后,电脑往往不能自动加载我们想让他加载的驱动了,所以可以看到一个黄色感叹号在设备管理器的设备上,提示驱动安装失败什么的,这个时候需要我们手动添加驱动,之前的办法是修改.inf文件(驱动程序描述文件)里面的VID和PID与程序里面的对应,结果指定文件夹搜索驱动压根搜不到,之后一顿离奇操作发现了新大陆!(以下仅供CDC虚拟串口参考,其他设备驱动不一定有效)
  1. 进入设备管理器选择无法识别的驱动,选择更新驱动
  2. 按图操作
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 3号大坑
  • 每次更换了PID和VID之后一定要卸载驱动,重新插拔再看看,不然电脑会按照上一次的VID、PID记录,就比如我刚刚烧了一个可以识别两个设备的,然后换成了另外一个其实只能生成一个设备的程序,但是没有跟换PID和VID,然后电脑依旧显示找到了两个设备,自以为配置成功了,兴奋的跳起之后,点击了下卸载驱动,重新插拔,结果露出正面目,其实还是只有一个设备,好吧,回去继续改代码!
  • 3
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
STM32USBOTG的配置可以通过使用ST公司的官方软件STM32CubeMX来快速开发所需的框架。该软件可以帮助我们省去很多底层配置的时间,比如时钟分配等。如果还不熟悉这个软件,建议学习一下,因为它可以为我们提供很大的帮助。\[1\] 在配置USB时,首先需要确认板上的端口资源,包括VBUS、D-、D+和GND四条线。其中,VBUS不一定要接在芯片端口上,作为从机的话可以直接拉高到3V以上。D-和D+需要接到芯片的OTG FS或HS端口上,DM对应D-,DP对应D+。作为主机可以不接VBUS,也可以将VBUS接到芯片端口作为检测口。OTG_HS如果想使用的话,需要外接PHY,如果没有外接PHY,也可以将HS口配置成FS口。\[2\] 确认硬件配置后,需要确定所需使用的晶振,可以是外部或内部晶振。然后,可以使用ST官方的配置工具来生成相应的配置文件,如system_stm32f2xx.c,并将其替换到工程中。配置文件中可以设置USB的时钟频率,例如使用HSI来配置48M的晶振供给USB。\[2\] 配置完时钟后,需要对USB库进行配置USB库中有很多例程可供选择,根据需求选择相应的模式,如DFU升级模式或MSC模式。配置主要涉及USB_HOST、USB_DEV和OTG双向模式的选择,可以在usb_conf.h文件中修改对应的宏来进行配置配置完成后,理论上就可以成功移植USB库了。\[2\] 另外,如果需要使用多个接口的组合设备,需要确保STM32硬件支持的接口数大于或等于实际使用的接口数,并相应修改usbd_conf.h文件中的宏定义,如修改USBD_MAX_NUM_INTERFACES的值为实际使用的接口数。同时,还需要修改每个端点的地址。\[3\] 总结来说,STM32USBOTG的配置可以通过使用STM32CubeMX软件来快速开发框架,并根据硬件资源和需求进行相应的配置,包括时钟配置USB配置和接口配置等。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [stm32f407以太网及USB OTG快速开发](https://blog.csdn.net/liqinghan/article/details/63263270)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STM32 USB OTG官方库移植](https://blog.csdn.net/liu236141068/article/details/49889897)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [STM32配置USB组合设备](https://blog.csdn.net/qq_43332314/article/details/109624892)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱出名的狗腿子

你的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值