本帖最后由 creep 于 2017-9-28 22:37 编辑 ' U% t( ]9 F! g: S/ e8 l$ R3 |, g 之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥 @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。 关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。 ' ]3 }; q) f) f& A1 u , a& K4 ]$ D4 C! w$ O& p' W 0、复合设备) P4 Z' b0 P1 o+ R 1 _" R8 n) q/ |6 \9 _4 `# F CDC 类设备在枚举过程中最主要的信息存储在配置描述符内: : x7 W* y# f5 x7 |+ e* B/ _' ? + m' i3 x" j5 X7 d 如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型4 G8 L5 _- M: W4 [" J 和使用的接口。 一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。6 i8 w# K( @/ x1 P- ? $ z! }% m) B( E3 N6 F) m' m% D. A5 @ + \5 g) {! N8 Q; p [; w& r 1、USB库修改& I! J0 v; J2 ?2 ^ 6 K1 ~. N; q8 [9 t9 Z4 S 不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO$ n/ M- D5 K T! m; c7 \2 f% n5 o' \4 B 上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。 1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件: 6 O" [3 e% e3 Y. S) A4 H a)增加端点 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。. y8 `1 P y' k/ G, l* t 3 K. ~) X2 ^9 m- C/ `, j6 ] 设置增加的端点的FIFO b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口; C) u# L! q6 o& T4 l * Y q9 M5 B6 e8 E2 P8 L 0 t) X$ L3 o: Z0 p) Q+ m 2 K- ] ]4 y2 z6 I- S ! l5 R+ w, R, o4 m" I c)将设备描述符修改为复合设备模式 $ F, ~( P7 w; U# N4 W- k 9 E. l5 H \3 Z* C. f$ p 4 B9 v' l/ s3 N9 w9 W9 X) c d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组* [6 R+ R- a8 Q 此外还需要修改最大的接口数(好像2个VCP设置大于2即可)3 a! S& P2 G/ j# e* @! D 因为USB库中使用了maclloc申请内存,要适当调整栈空间。% v2 K! H2 D6 T% }- u: n2 Y0 v; k 下面是枚举的过程和安装好驱动之后的设备管理器显示: L; Z& C0 J; b4 X. c ; J1 y x% i6 B, Y/ T H' O 2 E7 a; H1 |- m- P) D/ R ! O' I2 L: P" `5 t3 V* t 测试代码如下:
具体发送方向为:# o# X4 n4 j/ H ( E9 y7 B K5 E- B1 ~. t9 N5 O 2)、3个VCP串口, 9 t# q6 j. F/ z. r 在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口 ( O9 S. E6 b* t3 {! L" | 测试代码如下:
# H x! M1 \9 [* ]$ x( c+ S- u USB收发数据测试如下(点开查看大图):& [. {5 j5 G# N9 h3 h% I( c % v& a3 p7 f' w+ B7 r0 z/ J" b + k/ F6 V5 ?+ ~ 2 、驱动INF文件 复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。& ]& e0 g3 O o& g G/ |$ A) P) Z : A- G- U1 X4 ?9 \0 z; @* V8 w' a 测试代码: - Q% k: _2 I/ {* ^+ O8 e |
最全USB HID开发资料,悉心整理一个月,亲自测试
USB Audio设计与实现
【MCU实战经验】+STM32F107的USB使用
圈圈发布USB图书第二版有感,以及分享一些我学习USB过程...
STM32F4-DISC 实现USB主机(U盘)和USB设备(虚拟串口)自动切换
STM32 USB-HID通信移植步骤STM32 USB HID键盘例程
【经验分享】在进行 USB CDC 类开发时,无法发送 64整数倍的数据
如何让CDC类USB设备批量接收64字节以上数据
用STM32F4实现的USB摄像头UVC,配合上位机可识别车牌
基于STM32的USB HID基础经验分享
endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));2 O$ \9 V! Z6 i) M
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
/* Prepare Out endpoint to receive next packet */0 D I" y1 b, o$ O3 h# @7 ~
USBD_LL_PrepareReceive(pdev,! l/ u3 J( E4 m) |; I/ T1 n
CDC_OUT_EP1,
hcdc->RxBuffer,6 `1 y4 S" O( }+ |( v6 X
CDC_DATA_HS_OUT_PACKET_SIZE);
/ l$ A4 z- l6 `$ b
这里怎么处理
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。+ H$ c$ A9 E" {2 H8 F3 d
2、没有数字证书的问题我也搞不定,这个目前没有办法,WIN7 32位可以强制安装驱动,但是64位或者win10好像只能禁用签名验证才能安装驱动。win10也可以使用系统自动加载的兼容驱动好像也能正常通信。
可以先了解下USB复合设备。
好的
好的 !!!
, y% G) ^) ? o) @8 b! _! j7 M
谢谢大神分享!!
感谢飞哥带路!