1.USB基础知识介绍
这里有一篇文章写的非常好不再重复造轮子
USB基础知识介绍:https://blog.csdn.net/Richard_Brown/article/details/106602288
2.USB设备介绍
常见的USB设备:U盘、鼠标、MP3、移动硬盘、数码相机、键盘、游戏杆、USB摄像头、USB打印机、USB扫描仪、USB话筒、USB网卡、USB显示器等。
我这里就以STM32F103C8T6为主控芯片,目的是开发一个USB设备用于跟电脑PC机进行通信实现电脑音量的控制,我称之为音乐控制器项目。
3.USB协议版本
USB协议的版本:
USB的协议版本有:USB1.0、USB1.1 、USB2.0和USB3.0等
注意:USB2.0并不是高速设备的代名词,因为USB2.0协议对设备的高速模式并不是强制的,而是可选的。如PDIUSBD12(USB芯片型号),是符合USB2.0协议的,但是不支持高速模式,只支持12Mb/s的全速模式。和USB芯片也有关系的,不要认为支持USB2.0协议就一定具有高速模式。
STM32F103的USB设备模式介绍(属于USB2.0)
USB设备模式
本章介绍OTG_FS控制器在USB设备模式时的功能。
OTG_FS控制器在以下情况时工作在设备模式下:
● OTG B类设备
─ 插入的是USB电缆的B端时,默认的是OTG B类设备模式
● OTG A类设备
─ OTG A类设备通过HNP协议切换到设备角色
● B类设备
─ 在ID线存在时,插入的是USB电缆的B端,同时USB全局配置寄存器的HNP位
(OTG_FS_GUSBCFG寄存器的HNPCAP位)为’0’时(请参考OTG 1.3版的第6.8.3节)
● 仅作为USB设备(请参考下图)
─ USB全局配置寄存器的强制设备模式位(OTG_FS_GUSBCFG寄存器的FDMOD位)
为’1’,将强制使OTG_FS控制器工作于USB设备模式(请参考OTG 1.3版的第6.8.3
节)。在这种情况下ID线无论是否存在,其状态都将被忽略。
注意: 在设计一个总线供电的仅实现设备模式的B类设备时,需要有一个外部的电压变换器,从VBUS取电,为芯片的VDD供电。
由图可知STM32作为一个简单的从设备还是比较简单的只需要把DP DM链接到PA11跟PA12管脚即可。原理图如下:
USB主机如何识别从设备的接入跟速度
其实就是根据D+、D- 的高低电平来检测设备的插入。
在USB集线器的下游端口D+和D-上,分别接了一个15kΩ下拉电阻;
在设备端,D+或D-上接了一个上拉电阻1.5kΩ(本图中是D+),低速设备的上拉电阻接在D-上,高速和全速设备的上拉电阻接在D+上。在当没有设备插入时,输入端的电平就被这两个下拉电阻拉到了低电平。当有设备插入时,接了上拉电阻的数据线,电平被拉高,根据被拉高的是D+还是D- 来判断是低速设备还是全速设备。
USB高速设备显示被识别成全速设备,然后通过集线器和设备两者的确认,再切换到高速模式。高速模式下,是电流传输,这时要将D+上的上拉电阻断开
USB只遵循主从模式通信的理解
注意:USB只遵从主从模式,即设备与设备、主机与主机不能互连。
为了解决这个问题,就有了 USB OTG(on the go),做法是:同一个设备在不同的场合下可以在主机与从机之间切换。USB OTG比USB多了一个ID引脚,ID接地,充当USB Host;ID悬空,充当USB Device。例如:手机通过USB OTG接入电脑,此时手机就是USB Device,电脑是USB Host;U盘接入手机,此时手机就是USB Host,U盘是USB Device。
至于USB OTG如何在主机和从机间切换,这里就不做介绍,这个涉及到主机谈判协议HNP(Host Negotiation Protocol),是通过HNP去实现的。我也是大概能看懂这几句话,这个不懂暂时跳过。
如何去描述一个设备是什么呢
答案是设备描述符:
USB主机如何知道插入的USB是个什么样的设备,这个设备有什么功能就是由设备描述符来决定的。
USB描述符的类型
USB1.1协议中定义的标准描述符有:
设备描述符(Device Descriptor)、
配置描述符(Configuration Descriptor)、
接口描述符(Interface Descriptor)、
端点描述符(Endpoint Descriptor)、
字符串描述符(String Descriptor)
USB2.0又新增了两个新的标准描述符:
Device Qualifier Descriptor、
Other Speed Configuration Descriptor
还有一些特殊的描述符,如类特殊描述符(HID描述符、音频接口描述符)、厂商自定义的描述符等。
设备描述的理解
USB(Universal Serial Bus)设备描述符是一种用于描述连接到USB总线上的设备的信息的数据结构。它提供了有关设备的基本信息,如供应商ID、产品ID、设备类别、协议等。
以下是常见的USB设备描述符字段和它们的含义:
-
Device Descriptor(设备描述符):
- bLength: 描述符的长度。
- bDescriptorType: 描述符的类型,对于设备描述符,值为0x01。
- bcdUSB: 指示支持的USB规范版本。
- bDeviceClass: 设备的类别。
- bDeviceSubClass: 设备的子类别。
- bDeviceProtocol: 设备的协议。
- bMaxPacketSize0: 端点0的最大数据包大小。
- idVendor: 供应商ID,由USB论坛分配。
- idProduct: 产品ID,由制造商分配。
- bcdDevice: 设备的版本号。
- iManufacturer: 制造商信息的字符串描述符索引。
- iProduct: 产品信息的字符串描述符索引。
- iSerialNumber: 序列号信息的字符串描述符索引。
- bNumConfigurations: 设备支持的配置数目。
-
Configuration Descriptor(配置描述符):
- bLength: 描述符的长度。
- bDescriptorType: 描述符的类型,对于配置描述符,值为0x02。
- wTotalLength: 配置描述符及其子描述符的总长度。
- bNumInterfaces: 配置中接口的数目。
- bConfigurationValue: 配置的值,用于选择配置。
- iConfiguration: 配置信息的字符串描述符索引。
- bmAttributes: 配置特性,如自供电、远程唤醒等。
- bMaxPower: 配置所需的最大电流。
-
Interface Descriptor(接口描述符):
- bLength: 描述符的长度。
- bDescriptorType: 描述符的类型,对于接口描述符,值为0x04。
- bInterfaceNumber: 接口的编号。
- bAlternateSetting: 可选择的设置编号。
- bNumEndpoints: 接口使用的端点数目。
- bInterfaceClass: 接口的类别。
- bInterfaceSubClass: 接口的子类别。
- bInterfaceProtocol: 接口的协议。
- iInterface: 接口信息的字符串描述符索引。
-
Endpoint Descriptor(端点描述符):
- bLength: 描述符的长度。
- bDescriptorType: 描述符的类型,对于端点描述符,值为0x05。
- bEndpointAddress: 端点的地址及方向。
- bmAttributes: 端点的属性,如控制、同步、批量、中断等。
- wMaxPacketSize: 端点支持的最大数据包大小。
- bInterval: 中断端点的轮询间隔。
-
String Descriptor(字符串描述符):
用于提供与设备相关的文本信息,如制造商名称、产品名称、序列号等。这些字符串描述符可以帮助用户和操作系统更好地识别和管理连接的USB设备。每个字符串描述符都有一个索引,它们包含在设备描述符、配置描述符和接口描述符中。
- bLength(描述符长度):字符串描述符的字节数。
- bDescriptorType(描述符类型):对于字符串描述符,值为0x03。
- bString:实际的字符串数据,使用UTF-16LE编码。字符串的长度是可变的,由bLength字段指定。注意,字符串描述符并不是以零结尾的C风格字符串,而是在数据中直接编码的。
- Language ID:对于字符串描述符,索引为0的字符串包含语言ID列表,该列表指示支持的语言。
- 索引:每个字符串描述符都有一个唯一的索引,从1开始。这些索引被用于在描述符中引用特定的字符串。
一些常见的字符串描述符索引包括: - iManufacturer:制造商名称的字符串描述符索引。
- iProduct:产品名称的字符串描述符索引。
- iSerialNumber:序列号信息的字符串描述符索引。
- iConfiguration:配置信息的字符串描述符索引。
- iInterface:接口信息的字符串描述符索引。
这些字符串描述符允许制造商在USB设备中提供易于理解的信息,以便用户能够识别设备并与之交互,而不必仅仅依赖于设备的硬件信息。
常见的USB描述符类型及其对应的编号
描述符类型(bDescriptorType) | 编号(bDescriptorType) | 描述 |
---|---|---|
设备描述符(Device Descriptor) | 0x01 | 描述连接到USB总线的设备的基本信息。 |
配置描述符(Configuration Descriptor) | 0x02 | 描述设备的配置和接口信息。 |
字符串描述符(String Descriptor) | 0x03 | 提供与设备相关的文本信息。 |
接口描述符(Interface Descriptor) | 0x04 | 描述接口的信息,包括类别、子类别和协议。 |
端点描述符(Endpoint Descriptor) | 0x05 | 描述端点的信息,包括方向、类型和最大数据包大小。 |
设备质量描述符(Device Qualifier Descriptor) | 0x06 | 用于USB 2.0设备,提供设备的速度和能力信息。 |
其他速度配置描述符(Other Speed Configuration Descriptor) | 0x07 | 提供USB 2.0设备的其他速度配置信息。 |
接口功率描述符(Interface Power Descriptor) | 0x08 | 描述接口的功率需求。 |
OTG描述符(OTG Descriptor) | 0x09 | 用于USB On-The-Go(OTG)设备,提供OTG设备的能力信息。 |
接口功能描述符(Interface Functional Descriptor) | 0x24 | 描述特定类型的接口的功能性信息,如音频、视频等。 |
MIDI接口描述符(MIDI Interface Descriptor) | 0x24 | 描述MIDI音频接口的特定功能信息。 |
注意,这只是一些常见的USB描述符类型,实际上还有其他特定领域的描述符和扩展描述符,用于支持更多的功能和特性。每个描述符类型都有其特定的用途和信息内容,帮助操作系统和应用程序正确地配置和与USB设备进行通信。
不同的描述符都有自己的结构体
这里引用的那篇博客由详细的介绍我这里就不在详细展开
USB描述符之间的关系
USB描述符之间的关系:一个USB设备只有一个设备描述符。
设备描述符决定了该设备有多少种配置,每种配置都有一个配置描述符;
配置描述符中又定义了该配置有多少个接口,每个接口都有一个接口描述符;
接口描述符中又定义了该接口有多少个端点,每个端点都有一个端点描述符;
端点描述符定义了端点的类型、大小等。
如果有HID描述符或音频接口描述符,则在接口描述符的后面。
一个设备至少要包含设备描述符、配置描述符和接口描述符,如果USB设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。
USB描述符之间的关系是一层一层的,设备描述符、配置描述符、接口描述符、端点描述符。
我们在快速开发一个USB设备的时候就是要配置一个描述符结构体,这样主机就能识别到我们这个设备是什么东西,也就可以实现通信或者控制。
这是描述符号之间的关系图:
主机在获取描述符时,首先获取设备描述符,再获取配置描述符,然后根据配置描述符中的配置集合总长度,一次将配置描述符、接口描述符、类特殊描述符(如果有)、端点描述符一次读回。注意:接口描述符、类特殊描述符、端点描述符不能单独获取,必须跟配置描述符以一个集合的方式一并返回。可以通过beagle抓USB数据看到,没有Get Interface Descriptor和Get Endpoint Descriptor的请求。
对于字符串描述符,## 标题是单独获取的。主机通过发送获取字符串描述符的请求和描述符的索引号、语言ID来获取对应的字符串描述符。
总结
- 开发一个USB设备需要知道是遵循什么标准
- 开发一个UBS设备要配置若干设备描述符
- 不同的设备的设备描述符不一样要选择合适的
- USB通信至少需要两根线D+ D- 识别要加上拉电阻