目录
链接快速定位
前沿
1 描述符讲解
1.1 设备描述符
1.2 配置描述符
1.3 接口描述符
1.4 功能描述符
1.5 端点描述符
1.6 字符串描述符
1.7 报告描述符
2 运行演示
链接快速定位
USB -- 初识USB协议(一)
源码下载请参考链接:USB -- STM32-FS-USB-Device驱动代码简述(二)
USB -- STM32F103虚拟串口bulk传输讲解(三)
USB -- STM32F103自定义HID设备及HID上位机中断传输讲解(四)
USB -- STM32F103 U盘(MassStorage)SDIO接口SCSI协议Bulk传输讲解(五)
USB -- STM32F103 USB DFU设备固件升级(IAP)控制传输讲解(六)
USB -- STM32F103 USB AUDIO(音频)Speak同步传输(Out传输)讲解(七)
USB -- STM32F103 USB AUDIO(音频)Microphone同步传输(In传输)讲解(八)
USB -- STM32F103 USB VIDEO(视频)Camera同步传输讲解(九)
前沿
前面两节主要是对USB的基本概念做了简单讲解,学习USB的最本质目的还是要回到USB的应用方向,接下来的几章主要讲解USB的各类应用,包括:
- 虚拟串口(环回测试)-- bulk传输(USB -- STM32F103虚拟串口bulk传输讲解(三))
- 自定义HID -- 中断传输(USB -- STM32F103自定义HID设备及HID上位机中断传输讲解(四))
- U盘 -- bulk传输(USB -- STM32F103 U盘(MassStorage)SDIO接口SCSI协议Bulk传输讲解(五))
- 在线固件升级(DFU)-- 控制传输(USB -- STM32F103 USB DFU设备固件升级(IAP)控制传输讲解(六))
- 语音录制及播放 -- 同步Out传输(USB -- STM32F103 USB AUDIO(音频)Speak同步传输(Out传输)讲解(七))
- 语音录制及播放 -- 同步In传输(USB -- STM32F103 USB AUDIO(音频)Microphone同步传输(In传输)讲解(八))
- 照相机 -- 同步传输(USB -- STM32F103 USB VIDEO(视频)Camera同步传输讲解(九))
- 复合设备 -- 中断+bulk传输(本章讲解)
由于前面的章节已经对HID和MassStorage进行了详细的讲解,这里只简单讲解一下描述符,具体的请参见:
- USB -- STM32F103自定义HID设备及HID上位机中断传输讲解(四)
- USB -- STM32F103 U盘(MassStorage)SDIO接口SCSI协议Bulk传输讲解(五)
1 描述符讲解
描述符是USB能够正常通信的前提,没有描述符,USB就不知道当前是什么样的设备,所以描述符在USB整个通信过程中占有十分重要的地位,所以这里重点讲解一下USB的各类描述符。
ST的例程为我们配置好了应用的描述符,我们不需要关注也能正常运行程序,但是我们这里讲解一下怎么通过查找资料来知道具体描述符的含义。
1.1 设备描述符
以下是STM32F103系列的符合设备的设备描述符代码(每个字节对应的含义可以在USB -- 初识USB协议(一)中查看):
/* USB Standard Device Descriptor */
const uint8_t Composite_DeviceDescriptor[Composite_SIZ_DEVICE_DESC] =
{
0x12, /*bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
0x00, /*bcdUSB */
0x02,
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
0x40, /*bMaxPacketSize40*/
0x83, /*idVendor (0x0483)*/
0x04,
0x50, /*idProduct = 0x5750*/
0x57,
0x00, /*bcdDevice rel. 2.00*/
0x02,
1, /*Index of string descriptor describing
manufacturer */
2, /*Index of string descriptor describing
product*/
3, /*Index of string descriptor describing the
device serial number */
0x01 /*bNumConfigurations*/
}
; /* Composite_DeviceDescriptor */
设备描述符顾名思义就是描述USB设备的基本信息,主要包括以下信息:
- USB版本号
- USB设备类型
- USB设备协议
- 端点0最大传输大小(最大64byte)
- 厂商向USBIF申请的VID(需付费,由芯片厂商提供)
- 设备PID(厂商自定义)
- 制造商的字符串描述符索引(描述生产这个产品的厂商)
- 产品的字符串描述符索引(描述是什么产品)
- 设备序号的字符串描述符索引(主要是芯片的UID)
- 配置的数量(一般为1)
制造商的字符串描述符索引、产品的字符串描述符索引和设备序号的字符串描述符索引主要是制造商、产品和设备序列号在字符串描述符的索引位置。
比如这里举个例子,以下三个是字符串描述符,分别是制造商描述符、产品描述符和序列号描述符:
const uint8_t Composite_StringVendor[Composite_SIZ_STRING_VENDOR] =
{
Composite_SIZ_STRING_VENDOR, /* Size of Vendor string */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/
/* Manufacturer: "STMicroelectronics" */
'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
'c', 0, 's', 0
};
const uint8_t Composite_StringProduct[Composite_SIZ_STRING_PRODUCT] =
{
Composite_SIZ_STRING_PRODUCT, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, ' ', 0, 'C', 0,
'o', 0, 'm', 0, 'p', 0, 'o', 0, 's', 0, 'i', 0, 't', 0,
'e', 0,' ',0, 'M', 0, 'S', 0, 'C', 0, '+', 0, 'H', 0, 'I', 0, 'D', 0
};
uint8_t Composite_StringSerial[Composite_SIZ_STRING_SERIAL] =
{
Composite_SIZ_STRING_SERIAL, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'S', 0, 'T', 0, 'M', 0,'3', 0,'2', 0
};
由下面代码可知,他们的位置也是根据索引号排列的,所以主机请求index为1的描述符,那么设备就发送制造商描述符给主机,告诉主机USB的制造商是什么。
ONE_DESCRIPTOR String_Descriptor[4] =
{
{(uint8_t*)Composite_StringLangID, Composite_SIZ_STRING_LANGID},
{(uint8_t*)Composite_StringVendor, Composite_SIZ_STRING_VENDOR},
{(uint8_t*)Composite_StringProduct, Composite_SIZ_STRING_PRODUCT},
{(uint8_t*)Composite_StringSerial, Composite_SIZ_STRING_SERIAL}
};
如果设备描述符的索引值修改了,那么String_Descriptor数组存放数据的顺序也需要相应的修改。
VID可以通过USB官网:USB_Members查看,比如这里的是ST的VID,0x0483的10进制是1155,我们在USB官网查看,如下:
1.2 配置描述符
配置描述符顾名思义就是描述USB设备的配置信息,主要包括以下信息:
- USB接口的数量(会在接口描述符讲解)
- USB的配置值(一般为1,根据设备描述符配置数量决定)
- USB的供电信息
- USB的最大电流
const uint8_t Composite_ConfigDescriptor[] =
{
0x09, /* bLength: Configuration Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
Composite_SIZ_CONFIG_DESC,
/* wTotalLength: Bytes returned */
0x00,
0x02, /* bNumInterfaces: 2 interfaces */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing
the configuration*/
0xC0, /* bmAttributes: Self powered */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
}
1.3 接口描述符
这里的接口描述符有两个,由配置描述符指定个数。一个接口描述HID设备,另一个接口描述MassStorage设备,详细的解释可以参考博主以前的博客。
uint8_t Composite_InterfaceDescriptor[ ] =
{
/************** 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 Mass Storage interface ********************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: */
/* Interface descriptor type */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints*/
0x08, /* bInterfaceClass: MASS STORAGE Class */
0x06, /* bInterfaceSubClass : SCSI transparent*/
0x50, /* nInterfaceProtocol */
1, /* iInterface: */
}
1.4 功能描述符
这里只有HID的功能描述符,主要是引出报告描述符。
uint8_t Composite_FunctionalDescriptor[ ] =
{
/******************** 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,
}
1.5 端点描述符
这里用到4个端点,分别是HID使用两个和MassStorage使用两个,具体的解释可参见USB -- 初识USB协议(一)。
uint8_t Compositet_EndpointDescriptor[ ] =
{
/******************** 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 */
0x02, /* wMaxPacketSize: 2 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 */
0x02, /* wMaxPacketSize: 2 Bytes max */
0x00,
0x20, /* bInterval: Polling Interval (20 ms) */
。
。
。
0x07, /*Endpoint descriptor length = 7*/
0x05, /*Endpoint descriptor type */
0x82, /*Endpoint address (IN, address 2) */
0x02, /*Bulk endpoint type */
0x40, /*Maximum packet size (64 bytes) */
0x00,
0x00, /*Polling interval in milliseconds */
/* 25 */
0x07, /*Endpoint descriptor length = 7 */
0x05, /*Endpoint descriptor type */
0x02, /*Endpoint address (OUT, address 2) */
0x02, /*Bulk endpoint type */
0x40, /*Maximum packet size (64 bytes) */
0x00,
0x00 /*Polling interval in milliseconds*/
}
1.6 字符串描述符
在设备描述符中已经对制造商描述符、产品描述符和设备序号描述符做了说明,这里仅对语言ID描述符做简单说明。
语言ID描述符相对很简单,就是告诉主机用的哪种语言编码,这里一般选择0x0409,使用美国的编码。一般使用最多的也是美国编码。
/* USB String Descriptors (optional) */
const uint8_t Composite_StringLangID[Composite_SIZ_STRING_LANGID] =
{
Composite_SIZ_STRING_LANGID,
USB_STRING_DESCRIPTOR_TYPE,
0x09,
0x04
}
; /* LangID = 0x0409: U.S. English */
1.7 报告描述符
参见:USB -- STM32F103自定义HID设备及HID上位机中断传输讲解(四)
2 运行演示
在运行演示之前,至少需要修改D+的上拉电阻控制pin脚和操作nand flash的函数,具体可以参考(具体的操作演示也需参见下面链接,这里就不多做解释了):
- USB -- STM32F103自定义HID设备及HID上位机中断传输讲解(四)
- USB -- STM32F103 U盘(MassStorage)SDIO接口SCSI协议Bulk传输讲解(五)
下载程序,在设备管理器能够查看到HID设备和大容量设备,证明枚举成功。