
本帖最后由 creep 于 2017-9-28 22:37 编辑 ) m# X, f1 ]% S" B2 m* h m$ V 之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥 @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。 , \# G2 n6 s0 p* \* v' K8 B1 J 关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。8 ^ l9 G! u; ]/ a* t o, k' F* F6 }5 N# \# @ % @. C# [2 b, k$ O! K 0、复合设备/ ?5 m, q. l1 O- A9 d/ h " Y0 ^" O' w9 d: S % Z. `# j4 o' }! u: y- x/ o CDC 类设备在枚举过程中最主要的信息存储在配置描述符内: ![]() 7 d7 Y0 |* K( f9 e& I3 W # H+ k6 a4 M4 ^) P N# S 如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型 和使用的接口。 + v% ?* \* c# g0 L) Y* C0 | 一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。6 W, }+ s& N! G7 Q0 a5 v 8 O8 q! Z9 Z5 Z# k3 `+ W% Z. g/ F 1、USB库修改 " p$ U( G+ h3 e* g 不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO 上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。( J: `( O6 `* ^5 z9 @3 P3 t! B 7 m- f0 {4 f6 R' I 1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:& L& ~ s" x- N) Z5 _* \4 n % Y. I/ G& C! _3 [! a6 s ![]() ! g/ G2 u: q/ g: a9 {; K a)增加端点; v8 |( E0 L4 m' Y" v; W4 A 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。% O" N; Z U/ H9 P% [ K1 P2 N ![]() 3 ^5 K* `, k' X2 y 设置增加的端点的FIFO + J- R- M% v( a7 {! `2 W 1 h" G5 P3 ^5 e( X9 S4 h ![]() - V- o7 p) Y6 ?' t7 p* v! _ b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口1 L; e m% N9 g4 T. d % U' \9 r# ~- N0 W ![]() ; h! S7 ]- g, V5 L9 G6 I9 Z+ b+ B - ^0 W; H5 g, E, g c)将设备描述符修改为复合设备模式# N3 {- O: U6 h* r q( q* n- j* O7 W1 ?' F H ![]() 5 v: J# r: e! `/ C d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组 * Y2 V1 L1 F; c8 f! Q# {6 |$ S ![]() 此外还需要修改最大的接口数(好像2个VCP设置大于2即可): f' S0 q9 a1 f( o* p4 j j 因为USB库中使用了maclloc申请内存,要适当调整栈空间。 _7 l- O+ ~3 c) l \ ![]() 下面是枚举的过程和安装好驱动之后的设备管理器显示: & r& h5 s/ Y* E$ Z* W* B' X/ @7 R ![]() ![]() / f5 u5 \ y8 U f# U. m ![]() $ n, I$ R% l- T- R & r0 U9 ]- `0 x3 z+ f 测试代码如下:1 [2 Y$ m0 i1 p6 i% r
![]() ( ~9 p/ ^( Y' O6 l! K+ g) D, c 7 i9 S! Y% ^5 W, W 具体发送方向为: ![]() : {3 _: u) K/ f' k$ W7 a# C 2)、3个VCP串口,; f |: e5 r% }) }# Q4 W 在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口 ![]() 测试代码如下: w& J" `, l' E) X; b0 w
USB收发数据测试如下(点开查看大图):8 i; r M, \+ v" B ![]() ![]() 2 、驱动INF文件 复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。5 N0 M' p4 w4 d8 ] : Z- ?2 p3 d5 l) o7 O 测试代码: 6 P8 k* C7 N6 v1 p ![]() |
最全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));3 |, ^1 }+ ~: }! F; K6 `- |
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));- K6 K+ I4 o* J. [
就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
/* Prepare Out endpoint to receive next packet *// i- f$ r. B2 |2 H2 V9 m8 u u
USBD_LL_PrepareReceive(pdev,
CDC_OUT_EP1,
hcdc->RxBuffer,9 N# D8 q; \) ~9 \: e
CDC_DATA_HS_OUT_PACKET_SIZE);
这里怎么处理
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。6 B4 j1 C `4 y5 x" m$ M
2、没有数字证书的问题我也搞不定,这个目前没有办法,WIN7 32位可以强制安装驱动,但是64位或者win10好像只能禁用签名验证才能安装驱动。win10也可以使用系统自动加载的兼容驱动好像也能正常通信。
可以先了解下USB复合设备。
好的
好的 !!!
4 T/ W, s% A$ [: K5 ^* K; n: a
谢谢大神分享!!
感谢飞哥带路!