
本帖最后由 creep 于 2017-9-28 22:37 编辑 2 ?4 |. c; l0 E7 h5 N 之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥 @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。/ C* O+ ]& ~% f 关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。 4 S r) f2 s0 |$ B; e/ p7 E0 b / @7 N$ e$ ^. r: k7 {1 [ # a, |, S. \6 e: S; N6 {' x 0、复合设备 : `* w. T I) \, m 2 Y# [* s$ } @6 V CDC 类设备在枚举过程中最主要的信息存储在配置描述符内: ![]() - V. P5 n; x' l) v 如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型 和使用的接口。 : V. c' H1 v' `- S3 r+ ~; S/ X 一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。 1 u% H6 C' W3 N- F& F 1 A+ D& G3 y0 q" G& q 1、USB库修改4 C* }) R( {, {8 ~, A 9 N. E. q7 q& I4 m( v # x1 w1 Z, |* |! \6 c+ Q 不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO 上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。 / l0 }' \) g6 D- C2 s+ e 1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:! C6 i! w" _& \ W# p6 A2 _8 w5 ]% v ![]() ! W. ~# f; T b . E$ m( j: t& p" t$ P) T( v0 z a)增加端点 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。' T% z' [5 q" v ![]() % K/ a& g8 K' I+ w 设置增加的端点的FIFO+ y& w1 X" a, ?- R& }6 g3 i- `! D# J0 r " U6 L) O2 P/ C: J3 m. N5 M. _ ' U" `5 d% x2 S2 G3 } ![]() 5 U8 s/ X4 ] `2 O& a0 G 9 U5 N& ^; i$ W) G/ l1 b3 v b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口4 ~/ b% ^" q' {6 } ) ?4 m0 |5 R1 B6 E2 c7 U$ X6 V; U 7 m/ Y# v* [4 d$ x4 e" B) h ![]() , K7 X6 L* J' p4 R/ d c)将设备描述符修改为复合设备模式 9 J+ N) j" Q; [5 w ![]() 0 N% W9 D! j7 e m! B+ V d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组 3 I# M+ {2 U4 v ![]() 此外还需要修改最大的接口数(好像2个VCP设置大于2即可)8 s. h t( g W1 Q5 i( R" { 因为USB库中使用了maclloc申请内存,要适当调整栈空间。 , h y: y% _" w9 z0 n- R ![]() 下面是枚举的过程和安装好驱动之后的设备管理器显示: ![]() ![]() ! v6 i- }. c' X ![]() 3 c. v( i# ]: d( r5 h & h4 R- p# H0 J 测试代码如下:: y6 }; V: ^, R7 { i
![]() 8 E: _7 m3 u2 Y* Q6 x8 H4 Q+ Z 具体发送方向为:, n: E6 m8 H2 E% p. {% @% M 9 M/ k+ o6 h5 S8 \1 ~& a ![]() , S' N' u% ?+ C- n, c4 H 2)、3个VCP串口," {, J6 `2 V2 D% v q7 b2 ^ 7 I+ I' m2 ?* ^3 l# Y7 P 在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口 ![]() 测试代码如下:
0 o3 U; L4 n8 S3 h5 U2 @' E USB收发数据测试如下(点开查看大图):6 F# v1 T! t2 [5 S- N ![]() }! _; J9 q/ A Y+ l5 b7 ~ ![]() 2 、驱动INF文件 复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。$ q5 y: a- @; j3 h, I 9 P6 a: `9 L! j$ E$ K 测试代码: ; q1 l M$ X6 {2 ^$ M/ H ![]() |
最全USB HID开发资料,悉心整理一个月,亲自测试
实战经验 | 选择USBX模块生成USB CDC ACM无PD的项目
STM32 USB HID键盘例程
刘氓兔的杂谈【001】-片上USB 高速PHY
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
【源码】STLINK-V3MINI 高速USB仿真器,成功改刷【高速CMSIS-DAP】
在线直播|无需编写任何代码即可在STM32上实现USB-C Power Delivery
圈圈发布USB图书第二版有感,以及分享一些我学习USB过程...
USB Audio设计与实现
【MCU实战经验】+STM32F107的USB使用
endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));* x% p( U- m$ d$ ?
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));. B O0 S S6 x' C
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));5 R& u8 X& E' e+ S
就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
/* Prepare Out endpoint to receive next packet */
USBD_LL_PrepareReceive(pdev,9 F$ C4 G& G3 ~
CDC_OUT_EP1,
hcdc->RxBuffer,
CDC_DATA_HS_OUT_PACKET_SIZE);, n+ G6 \! ]" g! R* Q
这里怎么处理
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。6 F7 W0 P2 z& X. N. v" G, t
2、没有数字证书的问题我也搞不定,这个目前没有办法,WIN7 32位可以强制安装驱动,但是64位或者win10好像只能禁用签名验证才能安装驱动。win10也可以使用系统自动加载的兼容驱动好像也能正常通信。
可以先了解下USB复合设备。
好的
好的 !!!
$ s, `4 g c5 F4 Z N- y6 n2 ]3 g
谢谢大神分享!!
感谢飞哥带路!