你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑 # K# A0 h4 ~/ a# h' b, N: r9 S
. L% h3 ^6 U  B/ O8 ~0 Y* u' a/ Q

4 O8 ]- S; W# \8 T         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
8 V$ A, _/ l7 b# H. t) \8 k+ Y  i0 S; x
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。
3 F& j! i& P5 D) i. R
8 D6 _" i1 [( A5 D4 n
  O& n/ m6 w3 U$ U0 D; P
7 b9 W" S  K2 h" Q& _8 r 0、复合设备5 h+ v, D. L3 ?3 F
6 x( r; ?" I3 E4 U. W

! d7 t2 |4 p  v4 e7 FCDC 类设备在枚举过程中最主要的信息存储在配置描述符内:1 J3 V$ P7 R0 l/ T8 {

$ A( G; x! {5 m/ ~5 Y7 H2 n
" @5 i; Z: O# ^ abfdf189-a154-49fc-bd00-ab9c51382987.png
! w" g, @1 g2 H( _
& q- A& u! j& z' R- [1 I  `
$ x* E6 d% c; ~) ^# h  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
# _& T+ s3 Q7 [7 w- ?$ S和使用的接口。
7 o- G/ u) |# y, b  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。" v1 H5 u+ \' c; A
/ q! U" W, m6 `8 I, F
% O$ h7 O9 G% i" v; g
1、USB库修改( |* U$ S0 l8 k+ l+ g
% z# T* _' @& U+ w7 S/ G
# {, r6 f  x7 m
8 F) w! Z& R# Y3 L
不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO
" I7 y% f, Q4 X% i5 p7 c& O- l* z上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。4 l2 v3 b! W/ ]4 K
8 v% n3 ^% O0 D- K" T* |! W6 N3 A( P
1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:3 p! Z. r7 d8 m

, o$ K! }# S. s 5ec90026-3c9b-4786-87e0-06cadbef4265.png   M/ E8 D3 g, P3 G- z" u# n$ x

8 S% w! ?  d  `  J
7 F9 f! d% W9 V2 O# Oa)增加端点
9 ?6 N! |% C1 T9 h0 H: _/ ], D 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。
5 p8 Q1 r, q% y0 v9 Y) C
/ I6 r7 H9 `  [. j4 {) k( L8 | 5b8ef82c-10a1-4d37-946b-ae60da254152.png ! U- F1 M' n0 X' W8 Y6 d5 n) _
& |, ]( B2 P; M0 y" J/ t# D. M
设置增加的端点的FIFO0 {# Q4 |. ?3 L* h
0 H1 K/ @( @* s

+ `* Q: ?( J8 r 0ddf6de2-e026-485b-8070-04514e83e56c.png   s4 E3 `1 x: F4 W: S0 p5 [

6 n- |  c! Q" g5 G! e5 }3 a& B( {, y' c* U/ e8 O  F- X# S
b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口, r% e! Y' C4 s- c5 R- k4 n

8 h0 }$ R$ E: u  P# {5 M; v/ e* O& o' E  y
48c4af14-a790-4617-8015-6c8f1131cdd4.png
6 d# o/ _+ y1 ]0 P" n, l9 O. _/ `9 b8 @# p$ |9 S/ ^3 ^  t
* C- Q- p; }+ P4 z$ z" r
c)将设备描述符修改为复合设备模式
* ~3 {9 T  p3 O5 l. N( g& o- v4 }( Q5 B
; Z# G# d; @8 p7 L+ m+ K
98db37ba-b3dc-45be-b228-1590afb41c85.png
% G6 Q: u, ]. n7 H
5 B2 W2 w! M0 r. {! Y, I7 M8 o1 |0 T1 ?1 ^  k9 E
d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组
' ~, t4 M2 L" n5 K! o6 L3 r: D# D
" v- Z( p0 w! u4 I3 h TIM图片20170928215619.png
+ S5 ?; N& f6 Y- M此外还需要修改最大的接口数(好像2个VCP设置大于2即可), T; ?5 A3 d8 K8 M
因为USB库中使用了maclloc申请内存,要适当调整栈空间。9 o, C; ]( Q/ _+ T( c4 v/ m
% _& B" n' e. D5 I
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png - C1 T) n4 z8 w- U- m9 W

" J- e$ x4 _% ?8 L' |下面是枚举的过程和安装好驱动之后的设备管理器显示:! @9 \# Z0 B6 O: X. j% f# C
- B6 ?% j& l: k- @% ]7 Z8 m. U/ d

8 F" a# n( k6 E8 j b1c85265-21c9-4197-9d29-b539741de625.jpg $ x3 [  |4 ]/ J# M& S' P
5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg
& U) h  S* n+ b2 [5 t: E. C
5 e3 m7 j; z: t2 J9 n0 _& ]5 G$ i7 b2 G, E$ _% X1 Q4 P' \/ j1 d1 ^( ]
ed917e76-1d1c-4323-8bbc-dccf431f929a.png % x3 U2 Z" c' N0 V- S% G' N

' f0 C! \% t, e- o8 H* n/ \: u7 Y# Z- k, c" l; u' T
测试代码如下:" r$ @8 g: X5 Z) b" h2 O) M: [  n
  1.   while (1)
    + K; ^6 S6 F: l, b* x! L
  2.                 {. z5 d' ^: i4 ~1 s0 s
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
      x  t* P% g% M7 Q: V7 y
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);  n' Y, \& D2 E+ ?. X' P" _* F
  5.             HAL_Delay(1000);# t6 Y, E! a* R) P0 [
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    # d( t" U5 v5 @: \. U
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);6 r" X7 ~, q+ K5 U) M
  8.             HAL_Delay(1000);      $ r8 k; R! z3 J0 {% c
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图):
+ D: }* s6 D6 O$ [( O- P3 K7 B test1.gif + T, `' X3 O  \# U1 A# d

- K6 @7 G. T) C3 o1 r8 U, M
* J; z* t# A9 i: U4 b- w具体发送方向为:
3 D; A: m: x$ b* u) [/ q, M0 Q# ^
* o. f4 k% o0 e5 A
. Y8 F: C7 A- S( W+ j% C6 {3 x a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
- B: a' R2 M, U/ G: n8 ]
7 T9 k5 v1 E3 l2 @6 y4 @, c2 d
2 q# r7 p; H4 c3 i2)、3个VCP串口,
. Y4 z/ p% v' F. D$ Z" r7 o  R' J/ W8 L+ T9 X
在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
/ M; ?' t5 }3 S: Y7 M
5 S' @$ [# r8 z/ c9 q d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png + ~( I5 {  d( F# H$ X0 {
测试代码如下:
0 v5 C/ x/ y0 @0 h$ c2 S
  1. while (1)# k2 J" @7 ?5 a! \8 ^& ?; w
  2.                 {
    8 @+ }- J) s. ?; G
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    & Q( g, K* Z' C
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);% i$ ?4 M2 X0 ^' k7 M4 P
  5.             HAL_Delay(1000);
    + b( e2 U8 u" z
  6.             memcpy(TestBuff,"This message from VCP1\n",23);/ G( b2 l/ Y5 i# O% ]
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);1 k2 X2 g# B9 \/ y8 w
  8.             HAL_Delay(1000);     " m6 M# C3 p, U% @- M+ U' S
  9.             memcpy(TestBuff,"This message from VCP2\n",23);1 X/ J) k: v% ]: ]+ ?5 ~
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    ' M3 g1 u4 t3 ^7 U' H2 a2 t; b% q8 Z
  11.             HAL_Delay(1000);       # o) D4 G6 j$ y4 d
  12.                 }
复制代码

: `& t  j: s/ ]( `. b0 w- `& N3 ~2 \% O  e* V/ N+ }
USB收发数据测试如下
(点开查看大图):
8 F; ?) F! z/ V1 y) u test6.gif % @4 k, |7 d8 {# w7 y
9 ]3 `8 g6 n) j0 J
373b1865-5fcd-493b-9972-f02d2b90dd98.png $ L5 N8 p& t% Q) c

6 d& X: y- K0 k6 C" t. h% h2 、驱动INF文件. A8 M/ D6 j5 y. F! a
- H4 }( l; t$ R6 O9 F( J( U, m$ l
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。
4 z1 M2 H- R  _' B5 E# k: M! x
3 X- v9 u1 O4 C" z  X! {测试代码:8 d2 M' Y9 J) Q, }

/ ^, }+ p4 f" G% C6 |. S* q Two-VCP-HS.rar (1.19 MB, 下载次数: 1897)

点评

厉害,研究得比较深入  发表于 2018-1-11 14:31

评分

参与人数 5 ST金币 +73 收起 理由
零壹 + 1 赞一个!
kylongmu + 20 很给力!
g921002 + 10 很给力!
wofei1314 + 22 神马都是浮云
zero99 + 20

查看全部评分

赞 5 收藏 53 评论136 发布时间:2017-9-28 22:30

举报

136个回答
wylew 回答时间:2018-2-6 09:25:22
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:
% A6 N6 f' F' C, |& Oendpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
. j2 ~2 z  N# Z6 yendpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
# t* h/ ?$ ?0 T# a+ G  b3 i& Sendpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
- r, p' m# _& V/ [) W9 t就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错
, t- W9 @# S9 {% E0 t! M4 e      /* Prepare Out endpoint to receive next packet */* K  B6 P, n3 j6 d7 U" k
      USBD_LL_PrepareReceive(pdev,8 l5 Q. U9 N* b! X- @# R9 T
                             CDC_OUT_EP1,
9 p4 T. `  j! n9 Y4 `% F                             hcdc->RxBuffer,, v" I5 f, ]0 H8 I( C! h% N3 E, R
                             CDC_DATA_HS_OUT_PACKET_SIZE);
; ~- }- k* Q' q' ]- x7 _  V  |: \  Z( A8 Y% `
这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:35
8 ]4 o3 M3 e, i7 I现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...

3 q2 J% {; I1 ?0 Y1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。9 m/ Q  X& K, f( Q0 Y% J1 G2 \( y) I
2、没有数字证书的问题我也搞不定,这个目前没有办法,WIN7 32位可以强制安装驱动,但是64位或者win10好像只能禁用签名验证才能安装驱动。win10也可以使用系统自动加载的兼容驱动好像也能正常通信。
anny 回答时间:2017-9-29 08:55:31
多谢分享!!!
gujiamao 回答时间:2017-9-29 09:09:50
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个
creep 回答时间:2017-9-29 09:52:37
gujiamao 发表于 2017-9-29 09:098 x$ I) T! V3 ]  m
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...

1 C! u% `$ U$ Z# w8 c可以先了解下USB复合设备。
七哥 回答时间:2017-9-29 10:12:38
这个比较有用,以前没搞明白端点怎么加,枚举描述等跟我之前理解一致。
zero99 回答时间:2017-9-29 10:30:09
膜拜一下大佬  
gujiamao 回答时间:2017-9-29 11:12:51
creep 发表于 2017-9-29 09:52
7 z  ^/ }5 ?  R* s  b6 b可以先了解下USB复合设备。

9 Z4 Q7 [5 l) h! J0 v# t8 E9 W好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:522 }: }7 b2 ?( J1 p
可以先了解下USB复合设备。

5 F5 g, x, u9 ^' }好的 !!!
adlu 回答时间:2017-9-29 11:24:17
厉害!
斜阳 回答时间:2017-9-29 11:45:05
大神之作。mark备用
党国特派员 回答时间:2017-9-29 13:07:29
这个绝对要收藏...
wofei1314 回答时间:2017-10-10 22:55:38
膜拜~
0 a/ P* G$ l* E* I0 ?4 O* E! `7 z# s8 c, Y: T
谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55
* A& J( J' a2 S& v. W5 T  \膜拜~
* g7 U4 c3 V1 T  C3 ~# B. X* `8 C
1 H- t% Q& s* d( [谢谢大神分享!!
8 T9 p# y6 U0 W9 k3 I& s& @
感谢飞哥带路!
wofei1314 回答时间:2017-10-13 09:36:15
又看了一遍,好详细!!!
唯有奋斗 回答时间:2017-12-30 08:58:42
您好,请问一下STM32F4能虚拟出几个VCP呢?

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版