![shequ.stmicroelectronics.cn](./template/st_v1/static/img/logo2.png)
STM32U073的usb问题。
STM32F103标准库配置的虚拟串口,设备描述符请求失败
STM32L4R9最大支持SD卡的容量是?支持SDXC 64G卡吗?
USBX在F407上创建CDC不能正常使用
stm32F407作为usb device时,PC发数据下去,为什么会收到一样的数据?
USB复合设备MSC+CDC,MSC异常影响CDC收发
STM32F407 作USB host 驱动 声卡 问题
STM32F407 USB 的FIFO究竟有多少空间?
stm32f103 usb iap
USBH CDC通讯,如何修改通讯波特率?
刚好,我做了个USB转7路串口的模块,还在博客写了篇文章,应该能回答你的问题。
先上参考资料: ST社区的: <<USB CDC类入门培训.pdf>> STM32 USB如何配置多个CDC设备 状态与枚举过程 CDC串口之从认识到认知
USB CDC 类基础
CDC(Communication Device Class)类是 USB2.0 标准下的一个子类,定义了通信相关设备的抽象集合。它与USB2.0标准以 及其下的子类的相互关系如下图所示:![CDC-PSTN之间的关系.jpg CDC-PSTN之间的关系.jpg](data/attachment/forum/202407/31/092336tm19j1t4vgjg99g7.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
USB2.0标准下定义了很多子类,有音频类,CDC类,HID类等,通信类CDC下面,又有一些子类,这里我们主要使用PSTN(Public Switched Telephone Network)。从 PSTN官方标准文档来看,PSTN子类是一个与电信相关的子类,而这里,我们只是将它作为一个普通的通信设备使用,并没有使用到它的一些电话特性。PSTN定义了三种模型:DLM(Direct Line Mode),ACM(Abstract Control Model)和 TCM(Telephone Control Model). 一般选择ACM模型,个人估计是该模型控制接口传输的高层指令支持比如设置、获取波特率,设置获取与通信相关的参数,与串口控制,数据传输比较接近。 USB转串口,根据设备类型主要分为USB VCP串口、USB转CDC串口、HID转串口。USB HID从Win2000版本起内置驱动,是真正意义上的免驱,CDC串口驱动从Win10系统版本才开始内置,因CDC协议的用途定位,串口功能较其他方式并不完整。VCP串口驱动只需安装一次也可以联网自动安装,且有部分操作系统会内置厂商VCP驱动。根据实际使用情况,做了下对比汇总:![CDC_HID_VCP类对比.jpg CDC_HID_VCP类对比.jpg](data/attachment/forum/202407/31/092357z7k8pp4rsmrf5qml.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
基于CDC-ACM协议开发纯USB传输应用还是十分方便的,工程师只需要关注USB设备本身的开发工作,驱动软件甚至是应用软件均不用开发。 VCP串口主要是指使用厂商专用USB转串口驱动和通信协议实现的串口,该方式也最接近16C450/16C550等原生串口。HID转串口USB传输速度没有CDC和VCP快,不适合较高波特率通讯,且不兼容串口应用软件。
USB设备、接口、端点描述符
USB 协议已规定好支持的设备,主机系统中也准备好了许多对应设备的驱动程序。USB 设备第一次连接到主机时, 主机要知道是哪一类的USB设备才能指派对应的驱动。要知道占用多少资源、使用了哪些传输方式以及传输的数据量等,才能真正开始工作。这些信息是通过存储在设备中的USB描述符来体现的。 一个USB设备只有一个设备描述符,设备描述符里面定义了该设备有多少种配置,每种配置有对应的配置描述符;而在配置描述符中又定义了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;端点描述符定义了端点的大小,类型等等。由此我们可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。其中可能还会有获取设备序列号,厂商字符串,产品字符串等。详细关系如下图所示:
这些描述符是以字节流的形式传输的,所以软件代码里一般是用数组或者结构体封装。根据协议,主机有询问设备描述和配置描述符的SETUP指令,接口和端点的描述符都包含在配置描述符里。标准的设备描述符如下:
第1个是描述符长度,以字节为单位,第2个字节是类型,描述符基本是这样的开头,后面是该类型下描述符信息。配置描述符以及所包含的接口描述符,端点描述符定义如下:
配置描述符:
接口描述符:
端点描述符:
CDC类设备 CDC类设备与其他标准USB设备枚举过程的并没有什么特殊的地方。在设备描述符内可以使用DeviceClass=0x00, SubClass=0x00, Protocol=0x00 表示此类信息在接口描述符内给出;或者也可以使用0x02,0x00,0x00;来表明该设备为 CDC类设备。或者使用0xef, 0x02,0x01表示当前为复合设备。 USB CDC类配置描述符的结构:![CDC类描述符结构.jpg CDC类描述符结构.jpg](data/attachment/forum/202407/31/092536pojyoqq1yq1uz1qq.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
如上图所示,CDC类的配置描述符(1个串口)一般包含两个接口(Interface 0),一个控制接口,另外一个是数据接口(Interface 1), 除此之外,还有一个虚线指向的IAD(Interface Association Description),这个表示这个是不是可选的,得根据实际情况来确定其是否真实存在。
USB设备状态与枚举过程
USB协议规定USB可见设备状态分为连接(Attached), 上电(Powered),默认(Default),地址(Address),配置(Configured)和挂起(Suspended)6个状态。所谓可见,即USB系统和主机可见的状态,其它状态属于USB设备内部状态。
USB2.0协议CDC类设备枚举过程详解
检测电压变化,报告主机 首先,USB设备上电后,一直监测USB设备接口电平变化HUB检测到有电压变化,将利用自己的中断端点将信息反馈给主控制器有设备连接。
Host了解连接的设备 每个hub利用它自己的中断端点向主机报告它的各个端口的状态(对于这个过程,设备是看不到的,也不必关心),报告的内容只是hub端口的设备连接/断开的事件。如果有连接/断开事件发生,那么host会发送一个 Get_Port_Status请求(request)给hub以了解此次状态改变的确切含义。Get_Port_Status等请求属于所有hub都要求支持的hub类标准请求(standard hub-class requests)。
Hub检测所插入的设备是高速还是低速设备 hub通过检测USB总线空闲(Idle)时差分线的高低电压来判断所连接设备的速度类型,当host发来Get_Port_Status请求时,hub就可以将此设备的速度类型信息回复给host。USB 2.0规范要求速度检测要先于复位(Reset)操作。
hub复位设备 主机一旦得知新设备已连上以后,它至少等待100ms以使得插入操作的完成以及设备电源稳定工作。然后主机控制器就向hub发出一个 Set_Port_Feature请求让hub复位其管理的端口(刚才设备插上的端口)。hub通过驱动数据线到复位状态(D+和D-全为低电平 ),并持续至少10ms。当然,hub不会把这样的复位信号发送给其他已有设备连接的端口,所以其他连在该hub上的设备自然看不到复位信号,不受影响。
Host检测所连接的全速设备是否是支持高速模式 因为根据USB 2.0协议,高速(High Speed)设备在初始时是默认全速(Full Speed )状态运行,所以对于一个支持USB 2.0的高速hub,当它发现它的端口连接的是一个全速设备时,会进行高速检测,看看目前这个设备是否还支持高速传输,如果是,那就切到高速信号模式,否则就一直在全速状态下工作。 同样的,从设备的角度来看,如果是一个高速设备,在刚连接bub或上电时只能用全速信号模式运行(根据USB 2.0协议,高速设备必须向下兼容USB 1.1的全速模式)。随后hub会进行高速检测,之后这个设备才会切换到高速模式下工作。假如所连接的hub不支持USB 2.0,即不是高速hub,不能进行高速检测,设备将一直以全速工作。
Hub建立设备和主机之间的信息通道 主机不停地向hub发送Get_Port_Status请求,以查询设备是否复位成功。Hub返回的报告信息中有专门的一位用来标志设备的复位状态。 当hub撤销了复位信号,设备就处于默认/空闲状态(Default state),准备接收主机发来的请求。设备和主机之间的通信通过控制传输,默认地址0,端点号0进行。此时,设备能从总线上得到的最大电流是100mA。(所有的USB设备在总线复位后其地址都为0,这样主机就可以跟那些刚刚插入的设备通过地址0通信。)
主机发送Get_Descriptor请求获取默认管道的最大包长度 默认管道(Default Pipe)在设备一端来看就是端点0。主机此时发送的请求是默认地址0,端点0,虽然所有未分配地址的设备都是通过地址0来获取主机发来的请求,但由于枚举过程不是多个设备并行处理,而是一次枚举一个设备的方式进行,所以不会发生多个设备同时响应主机发来的请求。 设备描述符的第8字节代表设备端点0的最大包大小。虽然说设备所返回的设备描述符(Device Descriptor)长度只有18字节,但系统也不在乎,此时,描述符的长度信息对它来说是最重要的,其他的瞄一眼就过了。当完成第一次的控制传输后,也就是完成控制传输的状态阶段,系统会要求hub对设备进行再一次的复位操作(USB规范里面可没这要求)。再次复位的目的是使设备进入一个确定的状态。
主机给设备分配一个地址 主机控制器通过Set_Address请求向设备分配一个唯一的地址。在完成这次传输之后,设备进入地址状态(Address state),之后就启用新地址继续与主机通信。设备在,地址在;设备消失(被拔出,复位,系统重启),地址被收回。同一个设备当再次被枚举后得到的地址不一定是上次那个了。
主机获取设备的信息 主机发送 Get_Descriptor请求到新地址读取设备描述符,这次主机发送Get_Descriptor请求可算是诚心,它会认真解析设备描述符的内容。设备描述符内信息包括端点0的最大包长度,设备所支持的配置(Configuration)个数,设备类型,VID(Vendor ID,由USB-IF分配), PID(Product ID,由厂商自己定制)等信息。
接着说到描述符。总的来讲描述符就是USB设备之间通信的规范。当一个新的USB设备接入时,他的默认地址为0,此时主设备通过描述符识别从设备,并与其通信,来获得更多关于从设备的信息。并为从设备在1到127找到一个没有分配的地址。并将该地址赋给这个从设备,这样,这个从设备就可以使用新获得的地址和主设备通信了。
GET_INTERFACE(取获取接口) 这个请求向指定接口返回选中的备用设备。
一些USB设备有接口设置互斥的配置。这个请求允许主机确定当前选定的备用设置。如果wValue或者wLength的值与上面指定的不一致,那么设备的行为没有定义;如果指定的接口不存在,那么设备将用请求错误响应。
USB CDC 描述符实例
设备描述符:
设备描述符定义了USB 2.0设备;指明类别在接口描述符中给出;端点0的最大报文长度;USB 设备的PID, VID; 本项目是模拟了7个串口,配置描述符比较大,还是用数组直接写会非常长。在github上参考了别人的代码,用宏定义了串口描述,数组定义就简洁了许多。宏定义如下:
看代码的注释即可,不再说明了。
(end)
USB 虚拟串口,端点不能访问 (stmicroelectronics.cn)
stm32 怎么用cube生成多个usb 虚拟串口 (stmicroelectronics.cn)