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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑
8 Z3 F7 v+ P; S% j" S$ i
- K  P; o3 s4 u3 j3 i* G! Z3 X3 x# k! |) i4 |/ I  b
         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。4 Q/ z$ s: [0 Z; m7 x- \
7 z' D" k) k# E2 m: i
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。
9 x6 t5 L& y. `3 K/ S) H
7 D) u! X) v  W6 l1 u- j  I- J' S* G* H6 h5 t# u

8 M$ ~2 ^2 O  `/ v 0、复合设备
3 v2 k7 h. }/ y# Y$ y! ?
% x3 n8 ?6 J6 a3 v& n8 e8 J# j% n3 e4 F+ V- B* K$ h
CDC 类设备在枚举过程中最主要的信息存储在配置描述符内:) k$ {" O- S5 b+ E0 i
/ Y, T0 a+ O8 _. {
+ W& e# s' s3 v. _. `
abfdf189-a154-49fc-bd00-ab9c51382987.png
' b: D3 |/ n2 F' w. ^8 }3 n5 ~" Q
1 v( G3 f+ L4 ^6 s; }
/ o8 ]# D  F- u7 h5 ~8 I- ]8 L6 L  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型( K& I9 Z- w- G" b
和使用的接口。 & N6 P2 b8 W. [
  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。+ C6 s8 h$ l: r
* o! M7 [% H8 S* D! S, g

3 J, x. y- R+ z; B4 z1、USB库修改2 O) W- x  y8 b" I( @/ s4 e( f) ?
' s! \4 o3 O' M$ _

% G8 }+ E, Y; E. e7 \) k/ o% K+ d2 p, }  {/ ~! ^
不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO
; Z) U% \) G6 e0 X) O) T0 |上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。
7 x0 B+ L/ q$ I+ u, j8 l9 Y
8 S. U& P; b8 D' k% F1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:
# i; [$ |0 s- G9 i/ d: L; a$ e- F5 p) i4 W' ]
5ec90026-3c9b-4786-87e0-06cadbef4265.png
9 Y+ q. p# p# E0 q+ y' J4 U7 p& q% x. v1 h% q. j

8 y; ^% |+ t1 U6 N3 G" M; `: Wa)增加端点& r7 A0 B% F: t! _! {" v& Y( M
一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。
( S6 S  N! k% u$ L! B) B9 P4 G  }' R3 |- d" }4 `" h
5b8ef82c-10a1-4d37-946b-ae60da254152.png + Q. O0 S# _/ ?1 m
* ^4 ]' Q3 ?0 h: Z% J3 C
设置增加的端点的FIFO7 [% j) f) [, z5 g, u3 A/ F9 q

9 I0 o9 K( b: A) v
+ T, z/ m5 `+ {* t( `% n6 M 0ddf6de2-e026-485b-8070-04514e83e56c.png
( X4 V0 A4 E  E4 C) `& H) u, R# E5 i) c) F$ e. e7 Q! M/ l

4 J+ s+ h( C4 c# S$ e; w$ \b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口$ H3 n. N! H4 F% @, e3 w" o

$ i1 k% u. e- p& L6 |, b3 |5 ]0 v3 ]
48c4af14-a790-4617-8015-6c8f1131cdd4.png ( E2 f% P5 G+ s2 a1 [" Y' v

& Z, j4 A, `1 d
) ^) D; G5 Y0 Kc)将设备描述符修改为复合设备模式
+ R5 O+ q& A7 c/ ]& y( O+ I! O: \. r* s3 B* @1 n/ ~

2 K/ X7 `- C7 b3 l; M 98db37ba-b3dc-45be-b228-1590afb41c85.png # }: `; c; i: X3 e3 d$ ?
: E- D/ S) q1 B! S
" ?& m" x: t+ m! ^0 m% i1 l
d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组
" X9 y) L3 @0 x  S0 j# {* r7 {
$ J. k; j+ T7 K) N TIM图片20170928215619.png
2 x9 C1 Z0 l3 ^( Y此外还需要修改最大的接口数(好像2个VCP设置大于2即可)
$ J; ^' \# K6 h+ O8 l7 s. z因为USB库中使用了maclloc申请内存,要适当调整栈空间。
. r! v% J; w/ A( f( z. f, a6 v* x  v  `
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png
$ i& u, v2 E* z0 n7 j2 P) G( Q; e( ~1 c4 r- t! D
下面是枚举的过程和安装好驱动之后的设备管理器显示:& `/ c; }  B: V8 V- f2 B" \

9 h5 E; |1 e% M+ j" i
/ N2 a* o% B# ^3 R5 a b1c85265-21c9-4197-9d29-b539741de625.jpg
/ ^5 C0 g% F0 M 5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg
+ T/ j2 T! Y4 y6 [! H. v: f& N- A: j  m; i" r; I

" k  x! Z7 F$ G  V' @' G9 w ed917e76-1d1c-4323-8bbc-dccf431f929a.png
( o1 A' }* p, p; g4 U( j& Z" X. \7 I) O- E
+ z, X7 _; t, [& Y
测试代码如下:
/ \/ o( w3 }1 a
  1.   while (1), L: s: h3 V. {
  2.                 {) @; m+ ?: y; h+ E& o
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
      h' ^. |) G$ W# V
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);! Q$ y5 I1 m" P# q2 r
  5.             HAL_Delay(1000);7 M$ o. f$ C8 ?  I0 e7 y
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    5 [- o( K4 u# C3 a2 A5 y' A, I
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);, Q! z6 ~' x: v" T' N' F
  8.             HAL_Delay(1000);      
    " I6 S+ i+ N* D
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图)
. M5 p) T7 g; k, E5 @ test1.gif   e4 c. I  |1 v) q( j- Z- B

8 Y- `" w7 j6 g! `0 c  z5 O; q; y) }% o
具体发送方向为:
' A* ~# w0 ~! S! S) k8 |  a' o7 [. j1 ~+ k! j

- q1 M! h( ^$ _5 s a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
: e% h3 z' R) K
: o6 [& _( D& R0 t
2 L8 y# x& c8 h, P! f0 ?2)、3个VCP串口,
2 t2 r- W( o8 m$ f2 {! z1 J
0 t  |9 b3 v5 p' ]: q( M在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口' H" v3 [4 I& P: J
& M4 x$ T8 L( V/ k% e* f% I
d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png 8 j0 R% b  J' n1 a5 R- _; K
测试代码如下:: L6 N( C: v; r* X3 L. k
  1. while (1)+ e3 `/ `8 k" R) d$ R3 u/ ]
  2.                 {2 h, W+ R1 N8 e0 L1 a2 g* ~
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    . m2 r+ d6 m3 D+ y% n
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);# A, l+ ^4 O* F8 E$ S# E, e& M
  5.             HAL_Delay(1000);" U# X1 Q% F7 i1 u  n+ i& O
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    ( M3 I) s0 L6 B' q
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);; V) O' n2 M- h) W
  8.             HAL_Delay(1000);     / L0 P  E3 T! v" Q$ e
  9.             memcpy(TestBuff,"This message from VCP2\n",23);, [7 j' W) u. ~- T
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);* U$ l+ Q7 j& g6 c
  11.             HAL_Delay(1000);       # M  ]- M. {7 ]1 B1 ]
  12.                 }
复制代码

+ n: l1 y) b1 ?# r& j$ S$ E9 j+ G: U  A5 E  M% h% V' u! y2 T  \9 a
USB收发数据测试如下
(点开查看大图)' z, y) G$ N- v1 J! W% r
test6.gif
2 k3 ?2 P% a* R6 k# g+ Y6 d7 D2 \3 ?- O. J. x, M( A" q
373b1865-5fcd-493b-9972-f02d2b90dd98.png
- @5 l$ \9 Y1 l) I- p' }& w" a7 @* d8 i4 c) Y
2 、驱动INF文件+ u7 P4 ?8 L- ~9 f' f
& ~+ d. k7 M9 L
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。
9 ?0 Y( C# k  _, u
3 U# p, h" Z/ q% B测试代码:+ A8 ~, _- _# G4 c
* k! Z0 V; j$ W0 K% z% z
Two-VCP-HS.rar (1.19 MB, 下载次数: 1802)

点评

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

评分

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

查看全部评分

4 收藏 51 评论133 发布时间:2017-9-28 22:30

举报

133个回答
wylew 回答时间:2018-2-6 09:25:22
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:
, Q" E8 C. e- U* ]; Gendpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));! y6 X! O9 N, ~+ E: A1 h- V, o
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
9 X/ m. n+ G  {endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
$ z  ^$ j7 Z, W7 H* j+ z% X就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错
  S. h' H. j2 h: B      /* Prepare Out endpoint to receive next packet */
: Y6 i* }$ V. ]* h+ ~2 q0 ^      USBD_LL_PrepareReceive(pdev,
( L1 j" D! E9 i) r3 p, a                             CDC_OUT_EP1,
, C; m( Z2 N3 m. m  r! }* A                             hcdc->RxBuffer,
/ o& f4 U  g$ F                             CDC_DATA_HS_OUT_PACKET_SIZE);
6 U1 y$ _* Z" z) J+ N" w3 z3 M2 u/ K& g, ^7 Q
这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:356 N* S) y6 f* E! d2 Y% u5 j; q9 x
现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...
/ m5 L5 A. j+ P
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。  K5 ?, N4 t; M' \
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:09- R0 x8 f' Z6 S8 f% l8 u
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
) r) r( E4 G+ |$ f( w( L
可以先了解下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:529 M; x( U6 a$ c4 O3 S
可以先了解下USB复合设备。

7 ]) o! z( _: O. K好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:52
  J5 a, y3 H$ T* H) \( g" ~可以先了解下USB复合设备。

5 m0 m8 Z3 P. \; I# U好的 !!!
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
膜拜~
9 X, e; Y9 [9 o6 W: t/ h! `- m* q. g8 k( i/ r
谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55. e4 f8 F2 s% `7 [0 `
膜拜~6 l' p8 a9 y! K' W. Z
# {; N) d( M" q0 v, w
谢谢大神分享!!

! Q) e4 t1 P( P感谢飞哥带路!
wofei1314 回答时间:2017-10-13 09:36:15
又看了一遍,好详细!!!
唯有奋斗 回答时间:2017-12-30 08:58:42
您好,请问一下STM32F4能虚拟出几个VCP呢?
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版