前言

文中对于USB较为常见的描述符其中一些字节含义不做过多的描述。如果对其不太了解可以参考USB中文网的描述!
文章内容仅为个人学习记录,谢谢!

一、通信类型与描述符大致结构

1、通信类型

USB CDC类的设备下面有很多子类,ACM模型是属于PSTN类。常规的USB转UART就是使用其中的简单通信功能。

2、配置描述符大致结构

接口层有IAD描述符、接口描述符0、接口描述符1
IAD描述符:此描述符可以不使用,GD的例程中使用union描述符来描述符哪些接口是联合在一起的
接口描述符0:在图中接口描述符0作为控制接口,下面包含一些其它信息的描述符,然后还包含1个输入端点,当设备需要向主机发送异步消息时,通过此端点进行发送,端点发送方式采用中断传输模式。
接口描述符1:此接口描述符作为数据接口,下面包含1个输入端点,包含1个输出端点,一般数据的传输都通过这两个端点发送接收。
此外,端点0在枚举结束后,用于发送控制指令,例如设置虚拟串口波特率。
在这里插入图片描述

二、通信数据解析

下面所有的数据信息都为使用GD32 USB通信时,抓取的数据。

1、设备地址分配

主机在获取描述符前会进行复位和速度判断一些操作。完成这部分工作,进行以下操作:
(1)80 06 00 01 00 00 40 00 HEX
含义:主机发送获取设备描述符请求,获取设备描述符字节数为64个字节,此处发送的设备地址为0,设备回复的设备描述符字节数可以不为64字节
(2)12 01 00 02 02 00 00 40 HEX
含义:此处设备只回复了设备描述符的前8个字节的数据,首字节说明了设备描述符长度为18字节,后面无数据的输出信息为主机发送给设备的应答
(3)00 05 19 00 00 00 00 00 HEX
含义:主机在获取1次设备描述符后,给设备分配地址,上面05含义为设置设备地址,设置的设备地址为25,设备收到地址信息并开始使用后,设备回复应答。后续设备开始使用主机分配的地址开始通信。
在这里插入图片描述

2、设备描述符获取

给设备分配完地址后,使用新地址重新获取设备描述符,此处获取的设备描述符为完整的设备描述符
(1)80 06 00 01 00 00 12 00 HEX
含义:主机获取设备描述符,获取设备描述符字节数为18字节。

(2)12 01 00 02 02 00 00 40 e9 28 8a 01 00 01 01 02 03 01 HEX
含义:
第1-2字节:描述符为设备描述符,字节数为18字节
第3-4字节: 00 02说明使用的USB版本为USB 2.0
第5-7字节:02 00 00表明设备为CDC类设备,
8字节:40表示端点0最大1包数据为64字节
第9-10字节:厂商的VID,此处的VID是设备厂商从USB IF申请的VID,0x28e9为兆易申请的VID号
第11-12字节:厂商的PID
第13-14字节:厂商出厂编号
第15字节:厂商字符串描述符索引值
第16字节:产品字符串描述符索引值
第17字节:设备序列号字符串描述符索引值
第18字节:配置描述符的数量,此处只有1个配置描述符。获取完成设备描述符后,主机回复应答。
在这里插入图片描述

3、配置描述符获取

此处,主机会发送获取配置描述符请求,一次获取配置描述符、接口描述符、端点描述符、CDC类的其它描述符。
完整获取配置描述符的配置描述符数据为:
09 02 43 00 02 01 00 80 32 09 04 00 00 01 02 02 01 00 05 24 00 10 01 05 24 01 00 01 04 24 02 02 05 24 06 00 01 07 05 82 03 08 00 0A 09 04 01 00 02 0A 00 00 00 07 05 03
02 40 00 00 07 05 81 02 40 00 00 HEX

(1)09 02 43 00 02 01 00 80 32 HEX
含义:
第1-2字节:描述符类型为配置描述符,描述符长度为9字节
第3-4字节:一次性获取数据的字节数,数据大小为67字节
5字节:支持的接口数量为2个
第6字节:启动配置时设置的参数
第7字节:配置字节描述符索引
第8字节:设备采用插入的USB线进行供电
第9字节:USB总线最大供电电流为100mA。

(2)09 04 00 00 01 02 02 01 00 HEX
含义:
第1-2字节:描述符类型为接口描述符,描述符长度为9字节
第3字节:接口描述符编号
第5字节:接口描述符下有1个端点
第6字节:02表示此接口为CDC类的控制接口
第7字节:02表示CDC类模型为ACM类
第8字节:01表示支持AT指令集,此处虽然表示支持AT指令集,实际未使用AT指令。

(3)05 24 00 10 01 HEX
含义:
第1-3:描述符为header描述符,长度为5字节
第4~5:CDC版本为1.10版本

(4)05 24 01 00 01 HEX
含义:
第1-3字节:描述符为Call Management描述符
第4字节:不支持电话类的AT指令
第5字节:电话内容的接口号

(5)04 24 02 02 HEX
含义:
第1-3字节:描述符为ACM功能描述符
第4字节:02表示支持LineStateCoding,GetLineCoding,SetControlState指令,这几个指令在例程中被用做设置波特率、查看波特率、串口打开与关闭。

(6)05 24 06 00 01 HEX
含义:
第1-3字节:描述符为union描述符
第4字节:接口0为控制接口
第5字节:接口1为0的下级接口

(7)07 05 82 03 08 00 0a HEX
含义:
第1-2字节:描述符类型为端点描述符
第3字节:端点方向为输入方向,地址为2
第4字节:传输类型为中断传输
第5-6字节:端点一次最大传输8字节
第7字节:轮询数据的时间间隔。

(8)09 04 01 00 02 0a 00 00 00 HEX
含义:
第1-2字节:描述符为接口描述符
第3字节:接口号为1
第5字节:接口下有2个端点
第6字节:接口为数据接口

(9)07 05 03 02 40 00 00 HEX
含义:
第1-2字节:描述符为端点描述符
第3字节:端点为数据输出端点
第4字节:端点数据传输类型为批量传输
第5字节:数据最大一次传输64字节

(10)07 05 81 02 40 00 00 HEX
含义:
第1-2字节:描述符为端点描述符
第3字节:端点为数据输入端点
第4字节:端点数据传输类型为批量传输
第5字节:数据最大一次传输64字节
在这里插入图片描述
上图为获取的配置描述符图示:

4、字符串描述符获取

另外,在枚举的过程中,主机也会去获取字符串描述符,字符串描述符中包含、设备厂商信息、设备ID、设备序列号、和语言类型等信息,此处不详细描述
在这里插入图片描述

5、启动配置

在获取完描述符后,主机发送配置指令启动设备配置
在这里插入图片描述

6、配置指令发送及数据收发

在使用串口助手与设备通信时,会使用到LineStateCoding,GetLineCoding,SetControlState这些指令用于设置获取串口状态和设置串口
GetLineCoding命令:
(1)a1 21 00 00 00 00 07 00 HEX
含义:
第1字节:端点为接口类请求
第2字节:GetLineCoding请求
第5-6字节:接口号为0
第7-8字节:接收的数据长度为7字节

(2)00 c2 01 00 00 00 08 HEX
含义:
第1-4字节:波特率为115200
第5位:为停止位信息,0表示1位停止位,1表示1.5位停止位,2表示2位停止位
第6位:效验位信息,0表示无效验,其它效验依此递增
第7位:数据为8位

说明:此请求在例程中用于获取串口信息
在这里插入图片描述
SetControlState命令:
(1)21 20 00 00 00 00 07 00 HEX
含义:
第1字节:端点为接口类请求
第2字节:SetControlState请求
第5-6字节:接口号为0
第7-8字节:接收的数据长度为7字节

(2)80 25 00 00 00 00 08 HEX
含义:
第1-4字节:波特率为9600
第5位:为停止位信息,0表示1位停止位,1表示1.5位停止位,2表示2位停止位
第6位:效验位信息,0表示无效验,其它效验依此递增
第7位:数据为8位

说明:此请求在例程中用于设置串口配置
在这里插入图片描述
LineStateCoding命令:
(1)21 22 01 00 00 00 00 00
含义:
第1字节:端点为接口类请求
第2字节:LineStateCoding请求
第3字节:设置串口开启

(2)21 22 00 00 00 00 00 00
含义:
第1字节:端点为接口类请求
第2字节:LineStateCoding请求
第3字节:设置串口关闭

说明:此请求用于反馈设备状态
在这里插入图片描述
数据传输:
主机将数据发送到设备的地址为3的端点上,设备通过地址为1的端点将数据发送给主机,数据为123456
在这里插入图片描述

三、例程代码分析与使用

GD的USB库较为复杂,此处只说明一些有助于初学使用的部分

1、USB中断

在使用GD的MCU作为设备插入主机时,主机会发送复位信号,同时设备会进入USB中断,USB复位标志位会置位。当设备插入主机,复位标志没有置位,此时,需要判断USB线路是否正常。例如在使用IO口(例如PD13)接一个电阻到DP线上,当代码中设置的上拉IO不是此IO(例如PD13)时,主机在DP线上检测不到上拉会判断无设备插入,设备复位标志位不会置位,此时可以查看USB线路是否正常。
在这里插入图片描述

2、描述符

在USB初始化时,会将描述符信息作为参数输入到函数中,便于后续的操作。跳转过去可查看描述符信息。
在这里插入图片描述

在这里插入图片描述
在_std_dev_req函数数组中,包含标准描述符的枚举的处理函数,在枚举出现异常时,可以在这些函数下面进行调试。
在这里插入图片描述

3、CDC枚举和通信处理

在USB初始化时,会传入CDC类的处理函数,当需要进行初始化、设备枚举、通信时,会调用此结构体中的函数,如下图:
在这里插入图片描述
cdc_class结构体中,cdc_acm_init为初始化函数在主机发送设置配置请求后会进行调用,
cdc_acm_req_handler函数会对ACM类特殊的描述符进行处理,例如LineStateCoding,GetLineCoding,SetControlState请求
在这里插入图片描述

4、数据收发

在GD的例程收发数据是在一个死循环中。**需要注意,接收函数不是用于接收数据,主机发送完数据标志位置位后,数据已经被端点接收,然后存储到USB结构体中,此处的函数功能是设置下一次接收数据的缓冲区,在下次主机发送数据前必须重新进行设置。**代码中发送函数将接收到的数据进行发送。
在这里插入图片描述

四、总结

上面的枚举的设备只是一个简单的串口通信功能,仅提供一个参考,具体开发需要根据实际的应用去修改描述符、通信请求。

参考资料:
USB中文网 USB2.0规范
ST USB CDC类入门培训

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐