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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑 - B. `2 x' A. S) F' R4 ?: G' {- _% s/ L5 s

# U2 X1 Q0 d# L% L6 p/ b( O
' Q+ @* c8 {8 e/ T; e         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
# j- O5 Z% b# U$ @$ [  e/ U# Q6 B: i! T
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。
- i  C$ B5 V! C  E5 L8 `( C: l+ r. _
4 b7 w$ Q5 `4 j
1 Z8 ^8 \3 ^4 s  Y
0、复合设备/ J- z$ p+ P& r. i
; Z: T" v3 `1 p6 W9 p/ W* D/ h. l
; U4 e4 I' C; D  f
CDC 类设备在枚举过程中最主要的信息存储在配置描述符内:2 M8 [+ J$ o: o! u; N+ x
0 [6 u! ^& `' z% x, w, z
; h$ I# D* m' K2 O7 U
abfdf189-a154-49fc-bd00-ab9c51382987.png 3 J2 S; C$ s7 P8 o3 P/ N( I) F( C

5 D+ h# e  {6 s$ v2 B' a4 }. _
( F7 X1 h' u8 F- j1 S  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
  I1 U( ?+ m7 u" o0 n: {和使用的接口。 ( `, M) W" L( p1 m
  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。
. Q1 _* l, A* k4 C! h6 j1 V% l
9 h' _* r) B9 u# I, ]/ U2 J: N
; n: L/ H5 v4 m3 {4 j1、USB库修改
( L4 V" I, B: y& U. _  c+ j0 V& w$ D' `7 d; E

2 Y1 I) b8 Q( i- o/ d8 C, W3 U0 w
, L6 q! e) c, M8 {) D, n, j不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO
+ q- b! H& e+ ^" J* s7 U' Q/ S+ _上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。# P& g( ~- f+ i1 w. {+ S5 p

6 [+ I- m* |5 Y3 I8 P1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:, B; l6 ~0 r+ E# Y! R9 U$ W, [- m

% j8 r. h+ K' n& b$ S 5ec90026-3c9b-4786-87e0-06cadbef4265.png
* s1 _. }" E* B4 t8 {6 w) x8 Z: z" J& f: V
* f7 {  G* [. y7 K
a)增加端点% z9 v8 ?0 a- ?* R0 r* ~
一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。2 W$ _; e* d; `3 z% x- C9 E$ t
0 c; _" Z8 x+ z
5b8ef82c-10a1-4d37-946b-ae60da254152.png ( x- r* m; H3 }
% [: c" u$ n7 [4 C$ T
设置增加的端点的FIFO
; S3 H. [, k% Y. L
& s2 e0 }* g; b6 H9 Z: d1 h
2 A/ \) t: f0 A( n* ^/ x6 G* Q 0ddf6de2-e026-485b-8070-04514e83e56c.png
5 {4 {' z- S/ r
) ^( d* I5 g) \0 R8 |0 s  `( X5 ~2 F& j' P* V7 Q+ B; D2 l
b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口3 T. f! H: h$ S7 s% _" \

( B6 \) T5 q) E5 [+ {9 p' T( G- K+ z) F3 P# Z1 h% H3 K! D1 J2 \- S
48c4af14-a790-4617-8015-6c8f1131cdd4.png
& U0 T* M8 o1 B* C1 q. t7 u6 O' C
7 J1 i1 U7 G, D3 b! n
1 |8 ?) @- b6 T' g3 K- x. F* N  J( ]c)将设备描述符修改为复合设备模式
2 Y" H# R6 S1 y
/ I- C; f$ u, n  M
: v  m! p1 |7 \2 T 98db37ba-b3dc-45be-b228-1590afb41c85.png
3 T8 M) K: U& T/ A& G
: ^/ x" ~- l( m0 {3 E, p
0 X* u# B. g$ b# {d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组( ?. Q$ E; _3 k4 P* i6 O+ \

7 U; w4 b/ ~" D0 m TIM图片20170928215619.png
' l# Y: C9 @- q3 T9 P3 |# @( O此外还需要修改最大的接口数(好像2个VCP设置大于2即可)
6 N4 G0 a4 k# h$ X3 Z因为USB库中使用了maclloc申请内存,要适当调整栈空间。' h3 }1 ]6 p- H, O% _
" U. x" N% J( e3 D# F( u8 H/ A
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png
1 r' ^( G8 `* A9 o4 E3 q
8 z5 `/ f& D1 w+ J: b7 L2 p下面是枚举的过程和安装好驱动之后的设备管理器显示:) x5 Z# ]' M. V. `6 N+ O
9 ?" @3 r: n- Z# l! c4 s
. \( O$ T! m: {+ H' E$ a, f
b1c85265-21c9-4197-9d29-b539741de625.jpg
9 L- X( ?: H: a6 O1 d, P* p 5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg , C# T+ b6 h$ z& D4 L2 P) u
2 R! m& \: A/ P  n' E
" o" a1 b1 f4 b2 b. t, @) h2 W
ed917e76-1d1c-4323-8bbc-dccf431f929a.png / J! [: @5 ?' J, q" e! Y

% h- f" Y# r5 g; s2 ~3 m( T4 E
* K6 o. {8 z- Z  \4 F2 }$ l8 p. ^5 R测试代码如下:
0 S2 ~$ C: @5 h. j( a" k
  1.   while (1)
    # H  N( w) e% J/ I
  2.                 {% O" n! S: N1 P& p# X. t
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    # b: Z" ]3 X& U7 k
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);
    3 S" x+ D1 [. s5 {
  5.             HAL_Delay(1000);
    ! c7 P4 U9 w8 ?# F' N. }7 g+ B- e5 P
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    6 y- }9 }$ l" q, Q2 R) a
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);/ I: e7 t) S. X' Y- v0 h1 E
  8.             HAL_Delay(1000);        T8 v, y/ V6 `2 A4 o0 E
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图)
- [; a& K! S3 s, @1 W% h( q test1.gif
" }0 X4 T' h5 ~/ K/ B0 l2 ^; T; p' }
6 b$ q1 N( v: N
具体发送方向为:
+ q0 P7 o: x( f' w& D
8 J8 k( X0 m' }2 r+ I
" B: K) Q4 j* }: `+ ^ a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
6 }5 B, Q3 J9 Y" ?, J$ C$ c2 v4 r! Q: ^+ n- M; X3 x& [
( Z9 k# c7 H2 @" g" Z2 N
2)、3个VCP串口,
7 w3 C) u9 p7 `* l: a
0 S+ X6 f) o, u- m) R3 ^, r. S  @; z在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
' D; w/ S3 h7 v1 G2 Q9 D) x% ?: J; }+ t, y( A$ p
d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png
- s% u- Z& v0 y( @$ F测试代码如下:
) P6 K2 P3 x. E9 n# P2 w$ O) s
  1. while (1)
    4 u7 y7 z! e8 A1 G- p
  2.                 {' t/ }' ?, e9 o5 o
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    . P4 Y9 L! F( c. }) I2 j+ j
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);
    0 a5 o& f' O7 }7 }2 [* ~  @) n, a
  5.             HAL_Delay(1000);7 J; R8 d- ?6 h
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    9 x* ^7 d% d" }6 _$ a
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);' w4 s2 q7 J- S" j& G0 a
  8.             HAL_Delay(1000);     
    6 V$ N) i$ `+ V/ O5 C6 E
  9.             memcpy(TestBuff,"This message from VCP2\n",23);2 C9 }  V/ p* `
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    7 F' f8 D" }. C$ }9 Q9 p+ g' A8 d
  11.             HAL_Delay(1000);       ( Z, G, Q5 c" o( j% F
  12.                 }
复制代码

$ n5 S( q& i) s: X  x8 @* v# N1 U$ P! I* i+ j, H0 ~: L
USB收发数据测试如下
(点开查看大图)) y9 d6 h3 K" ^' O! l
test6.gif * y; `. Q. T3 ?. m) F* \+ B7 W
  ~8 U4 y! E; P7 }9 v' |
373b1865-5fcd-493b-9972-f02d2b90dd98.png
3 H; Z) P! l3 _0 z/ h0 ^$ v1 C1 c! Z% z3 v
2 、驱动INF文件
! B3 ~' E+ J/ ~$ K2 o( p- z8 @4 S# o9 D' O; E5 ^
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。' W! K* G1 }0 o: o# O3 d: g3 r

$ J0 i$ s2 r8 ]% q9 z测试代码:  Z/ d) W0 w, f; `' W
3 I- G! g# R; S: |
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
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:  Z4 T. o4 d( @: r. C: Y
endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));# D+ P4 [! |% n0 k1 G: K
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));) m; u# H) Z  J2 \1 P- ^$ D
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));) K. X- O5 C' @. a$ o" w: G  y
就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错$ M5 |- |+ P* k  \: m- N& K
      /* Prepare Out endpoint to receive next packet */: Z# ?' t; g" j4 N/ S7 J3 v' W
      USBD_LL_PrepareReceive(pdev,/ b0 c3 p9 `% H2 U
                             CDC_OUT_EP1,# H9 K* w; J% S- U  G( D) {
                             hcdc->RxBuffer,7 Y7 J3 ]" ]/ ^) e' N
                             CDC_DATA_HS_OUT_PACKET_SIZE);
% Y! F: H5 x/ Z2 d- _# W& P
) u: F  ~$ D# [这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:35
* H$ v; d. B! g2 ~$ `现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...
) e: x6 M1 K$ e, M# J8 M; s
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。- G7 e( V7 ?2 E; q3 z
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* n  \4 J/ E! c. W* I! Z) B
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
3 Q* ]3 n# N# N7 ^1 y
可以先了解下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
) @# u0 J' K6 ^6 P6 b) p- a1 d可以先了解下USB复合设备。
+ ~+ J4 X3 F5 o2 Q; M8 H
好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:52$ p, t. K- H, j7 _# Q, a! ^- p
可以先了解下USB复合设备。
( w& F% [, v, b
好的 !!!
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
膜拜~4 l' _) j. p# b4 {5 g1 n
  G% i/ C7 l' S8 |) S2 K% z
谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:550 h" ?0 |: I" |* `& b
膜拜~
! [4 b( P( P" X. ^+ v, ^( @+ N& ~9 t: j0 J$ }7 |
谢谢大神分享!!
2 E/ d: R. J" C
感谢飞哥带路!
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 手机版