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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑
" e3 ]! R* W- l# F+ S+ [9 V  r+ _6 ~" {3 K+ p/ @7 R  A. x' w

4 l$ e8 L/ N1 q& E: W7 h, ]         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
+ k7 m; U6 ?" r8 b
6 B* O. {% z, ?1 \+ r         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。  ~* U/ h2 V+ {8 p* Y
" L7 O8 J, [, z* H

1 H/ }5 Y( O* k0 z( r5 u
+ P' J( V0 X2 `* f# }7 c1 ~ 0、复合设备
3 n  e+ r% C$ }- i/ z/ k6 S- u% s( Y  a' W8 {0 g8 S" i: g

. a3 ], V5 h) w" w0 s$ DCDC 类设备在枚举过程中最主要的信息存储在配置描述符内:$ z/ L" B$ T( @2 u! q0 W

8 h" J0 G1 y# l' C: k3 X6 S
- X1 Y- R! ]/ h% L, N abfdf189-a154-49fc-bd00-ab9c51382987.png 8 F: X# s( p9 M

) W/ d- i; {5 r- M8 b* b
9 M7 ^9 F' W/ W: Q4 p  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
5 ]3 v' C" B/ A: q! ^和使用的接口。 ' A5 o! A1 E: V$ D
  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。) n9 _9 T+ n, ~& ]( T1 q

; m) e( K+ r. G- h/ ]1 z: A
' v8 ~- t' N% b8 W; p7 _1、USB库修改
+ `3 s1 P8 F. w
) }& ^0 q% ]( `' ~. h# M  Q0 ^1 f# D$ O

4 }# t, P5 `) m7 ^" k. H3 ^4 R不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO( H" Y" a, C/ g& Q/ t0 _5 K
上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。
+ {. i- f4 `0 T* ?+ _
/ N& i/ J& V# z3 g' B- O# D1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:  E/ W( F/ G: z

% S: w* r) `9 [' Z6 K0 D 5ec90026-3c9b-4786-87e0-06cadbef4265.png / Q; q9 D5 s/ r( \5 {3 h: w0 Y
9 n# h7 e/ d- t/ X
- r7 o: Z5 B( i$ s& J
a)增加端点; n! l2 ~4 H7 _" g; `8 j
一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。
8 |, G4 J/ |8 c+ h3 M
8 G! h% \: W3 H/ F# v 5b8ef82c-10a1-4d37-946b-ae60da254152.png : {: k0 Q! L$ s9 z& |' a! P
# F: Q2 {, A9 W* y  |
设置增加的端点的FIFO* R0 }+ j8 ^" O; \0 I

( e9 o% t& e6 U: {9 O
/ b" q2 c2 D% i! K  A1 }" Q" ^ 0ddf6de2-e026-485b-8070-04514e83e56c.png
% a! j) n; G. M* e. W' L2 I/ _! N* ]4 V' \
1 R. ^* T4 `( }' S
  @$ _4 Y4 [7 F  |8 Qb)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口
; h7 z3 _$ d$ E9 ]1 O+ F$ p0 \# ^& G. s2 `7 d- ?) G4 {. c
0 v  T+ s6 t4 ?1 {( W
48c4af14-a790-4617-8015-6c8f1131cdd4.png
, A# A9 g) j0 @" J4 Y4 B3 ]5 y# a1 Q* Q
: I# O4 M% j4 [7 {& i9 Q
+ P6 }& L3 {: H0 Qc)将设备描述符修改为复合设备模式
6 A' u1 F# [; q/ G
( M, v4 e/ q" M! c) J5 _% c# y
9 C" @$ N9 u7 O8 q! ?; f 98db37ba-b3dc-45be-b228-1590afb41c85.png 8 O* B# R' Q# R( L2 ^8 @5 x
  C% E6 N& r) a2 _$ e
& u' V- r( ^# E3 X  l- `: G4 P3 K
d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组" F6 x+ N, f4 _

4 J, A. ?1 ?8 o/ i. z; T$ F# | TIM图片20170928215619.png + w+ F* M9 k8 m3 c+ p, y2 e& L' z; E0 K
此外还需要修改最大的接口数(好像2个VCP设置大于2即可)
7 X0 P! j3 ]: y% f, ?因为USB库中使用了maclloc申请内存,要适当调整栈空间。3 i8 _; f* ^3 V" L; R4 G7 U

0 \9 e( A5 E1 B' ` 2a0963ce-d11f-4a48-aff2-f502028d0e1f.png
( _, U! y. f9 r9 T& D. P6 Y6 B& G- F
1 B0 i( c% B/ o. W2 w) w3 n下面是枚举的过程和安装好驱动之后的设备管理器显示:
/ V7 H5 u& h. J% _1 G8 b: W
- T! B' o; \" w5 H/ f0 e( J7 S, u) \  w) e- l' P
b1c85265-21c9-4197-9d29-b539741de625.jpg ; C2 e* R7 O$ P* \
5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg 9 e/ H# s5 [/ c5 f4 n. Z9 X
2 t, w& D5 W+ L. U/ C& c9 ^, f' R6 L
: O0 l+ T6 L/ _$ c/ G. k1 ~9 X
ed917e76-1d1c-4323-8bbc-dccf431f929a.png * [  ~) n- q2 _1 v- r. [+ C

" k6 b6 F. y; o8 w2 s9 r' O: i4 w9 ~# |
3 ^+ R0 q' r8 [. [$ \& s! D6 s- v测试代码如下:: R" Y1 q! L7 {2 U
  1.   while (1)
    4 V7 H% u3 P8 b* @( Q
  2.                 {
    * A( \6 r7 j, h: a5 C
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    7 v% o: l3 N6 t% Q8 H, S+ V# B
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);
    ) [* o' `2 K, M0 V1 ~. n( B
  5.             HAL_Delay(1000);
    5 L+ R  d( k. ]1 X! B$ ^4 Z2 _
  6.             memcpy(TestBuff,"This message from VCP1\n",23);* @- |" S+ u8 c' F* ~. {" f' j
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);: J8 U7 U4 ~- R; I9 m1 u% p
  8.             HAL_Delay(1000);      
    4 [, a8 B* V) H" h1 k2 M% t) L
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图):. h8 s. J# ^3 H9 C# H! L; P1 D
test1.gif
3 C* n) T' Q# J' k4 n1 A2 J
& k$ z" n  [6 a5 \) S2 [
: Y7 x% z6 N9 f9 {具体发送方向为:
5 `4 X/ E. E. W4 N6 P6 m! }% G
3 O$ G# G! Z/ _( V: N6 o
3 ?9 C) d& _8 `, c  o) | a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
( S; |2 V4 x: K+ V8 v( r7 x: a% C3 O  j4 S/ u! C/ @: X
- M# U$ X- s3 @3 V
2)、3个VCP串口,
# @% ], ?. p6 q. B5 B
* j: B' E8 x1 F1 _在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
* |+ F) b) [# }3 O
4 k( M" \! S6 c, ` d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png
! m0 E0 _" H) |" x. n. ~测试代码如下:
( g* j1 t! O$ I* \
  1. while (1)
    ! v' P. y: D1 K: Q* [
  2.                 {. Q+ e7 ~( u: D0 h5 Z( F2 a  C/ h
  3.             memcpy(TestBuff,"This message from VCP0\n",23);* ~" B9 O* ~8 z/ `' g
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);( s' \3 k# r  S: O% H! {% h6 I- L
  5.             HAL_Delay(1000);+ f3 p' p7 B; {, B' [% c
  6.             memcpy(TestBuff,"This message from VCP1\n",23);* Z  z/ V5 a1 e- m$ Y5 r
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);! }6 G& t+ j5 d: s
  8.             HAL_Delay(1000);     9 x% }9 y, P8 x  K9 b+ O
  9.             memcpy(TestBuff,"This message from VCP2\n",23);
    / p0 `& P# w; g" l/ ]
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);5 z& Y. A% u( W- D' d1 e; w
  11.             HAL_Delay(1000);      
    0 U, b* b8 P" C! r
  12.                 }
复制代码

7 u  i7 ?$ Y7 T) ?8 J" }( j* |- k
7 B: @+ C; ^7 U! N+ c( {7 ?' HUSB收发数据测试如下
(点开查看大图):
2 O: @3 s2 x8 L+ j7 ^# N3 [6 T" h test6.gif
: X# U! Q2 v. @( z. q# o4 Z3 J" Q3 ]- N7 E+ _. ]" d. f
373b1865-5fcd-493b-9972-f02d2b90dd98.png
! b7 \$ s$ n2 u, E- g" S0 O
% b$ Y, t# R' u5 j% f' O" _& k2 、驱动INF文件
7 e/ x  r; n6 n5 p) |/ C
# b- A- K+ v' M9 M7 l 复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。4 |% i/ A; L) p/ V8 \+ Q8 s* `% ~1 r
3 t/ ?, X, E! L) p. B% e
测试代码:- O0 ?( e1 M* `* O6 o2 y3 S/ F- w

4 y) L  ~; x6 G, C# B  Q# B2 ^% \ 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
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:
9 B! h: e: D2 A& O1 j" H% kendpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
5 y$ `* K, y6 _$ Tendpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));+ J7 V3 w! B3 H2 ~$ d
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
$ f2 J( h" C. X' x4 ~" e6 h就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错% m! ?" N7 w' G6 F+ r
      /* Prepare Out endpoint to receive next packet */$ T# m7 t# R8 Y, x0 p
      USBD_LL_PrepareReceive(pdev,- k! I$ R; F! X& L; O" Z3 a- U& |
                             CDC_OUT_EP1,
$ G1 p+ B9 A9 L' @$ ^! {8 i                             hcdc->RxBuffer,8 l6 R) Y2 c* J3 Q8 ^: s* q7 b
                             CDC_DATA_HS_OUT_PACKET_SIZE);& H7 p& \# W" ~( w8 f; s6 N- j9 x+ d
5 ^2 O$ l& @( G" p9 o
这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:35) D( h6 k# a$ K
现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...

+ r( k) L! `+ p7 O1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。- {# V2 ^6 q0 G( r# C
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
1 z; T4 Z, g% x- ^9 K版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
- b2 Y4 G1 E8 j  r$ Y) @( 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:52
4 |8 @8 p: \/ A( G. C: @* E可以先了解下USB复合设备。
1 J$ q" [1 @8 T) m- H0 F5 Q% e
好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:522 e7 E- A- A5 o  t  o6 i
可以先了解下USB复合设备。

, J7 q! G) m- v, i, O3 a好的 !!!
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
膜拜~2 G+ `9 b* G" b' U2 w

& H7 T+ e5 A7 P$ y谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55$ K4 y2 l* d! u* f5 }/ [, C" r1 `2 a
膜拜~, g9 R- `' I" q& A& k7 ?* j' H
, q" a3 @/ H  B% b& x5 W% {
谢谢大神分享!!

+ H1 S( E; J; \' k* F9 _+ e) i. |感谢飞哥带路!
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 手机版