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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑 & L5 `6 o0 N7 Q) t5 m( L
; B' `4 U. l. w0 n2 h8 `, i  U" X( O: c
9 y1 o, c$ {6 \# p# _- P. d
         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
, |& |. B* A7 {+ G( }1 p" \8 R7 f/ z) \  j# k. c; x; }
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。3 K6 f8 f  g5 A' F0 h$ [; f
; \1 x- K  r1 k
9 T1 ~. H* d, _) H7 s- {( [

9 B, g. ?+ ]: ] 0、复合设备
, P/ \+ I" D: {
( N" `) x% a4 _" k2 C  }  l6 a3 r) n5 K/ R) D* X8 x
CDC 类设备在枚举过程中最主要的信息存储在配置描述符内:! Z# i# j0 M1 {  k

- L: C6 Y$ J5 w" _% Z7 b, S7 _# I8 B& A
) M' q9 t3 y0 M1 _1 c abfdf189-a154-49fc-bd00-ab9c51382987.png 7 M9 Z* r' b6 N
. I) E# n) f$ M" V  M2 r7 |  S7 J
4 S7 M$ _- p' O6 n
  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
/ X4 e+ M" @3 c- v, E: F% E和使用的接口。 ; d; x  }% [4 G8 X! x
  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。* }! I  Q9 X" D, _. F

) m, I, y0 Y. v8 I4 `& f; `! [6 C& A$ M* H! Q, d
1、USB库修改
* Z# b0 A; E! r. B! q4 W& j- g) b- M4 x' u

  t4 Q% r7 Y* p* X: @) h- A6 b# i/ s" J( D1 @
不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO0 W, t# J5 c. n" E: X1 y: _
上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。- e0 H7 r+ O7 E5 B

5 @0 g5 f- g/ v$ N" l% \1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:
& V9 E) q. Q3 ~. r! L* |
) f5 _0 t4 p8 Q6 I; a 5ec90026-3c9b-4786-87e0-06cadbef4265.png 0 p- \( x/ j0 ~4 w! }2 e& x, w
" D! y' U6 u6 M& o# m! O

- N8 p( P( s. f: z/ r1 }* ba)增加端点
/ j& B( i7 e* I 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。4 d( g4 _" S  {7 C0 I% U
- `& L8 v- E; j$ X. A
5b8ef82c-10a1-4d37-946b-ae60da254152.png
( h) o2 W2 G+ r* D; k* z) d
( {( H9 S1 X6 O设置增加的端点的FIFO2 Q1 P* c" W2 Z: u
1 ]5 B; l* ?- \$ K
) o+ F% q9 O8 O) C! N& ]5 h: l
0ddf6de2-e026-485b-8070-04514e83e56c.png
" f, y+ Y. x- J3 Q4 _0 ^' p# N/ T1 w6 a: U- F

/ Q& a1 u* d0 o, W( O8 Hb)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口
& q4 a0 S4 G: D3 f5 I- \1 d$ f6 M$ M5 B, z+ D; C$ q# Y

" u. f" g) H' t  \, f5 H4 D6 N 48c4af14-a790-4617-8015-6c8f1131cdd4.png
/ ~2 _4 l8 d2 f1 U1 F. T" I# ~* Y, D
* L4 t. z, x8 H: @) G8 T; A" ~' O! M( w2 Y- ~0 b9 M$ e4 m- q
c)将设备描述符修改为复合设备模式8 R. ]2 g  t2 l0 X% g; M9 q/ W$ {
4 u4 l, ?6 m& s- k& ~1 O

  [& |" }5 `8 T: p5 |  Y 98db37ba-b3dc-45be-b228-1590afb41c85.png 8 D4 a1 [' f' y! D

( J. {4 z& a6 K' o
! c" ], Y3 w% y6 h  j; Fd)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组( W$ u9 n: h. ^' `0 w
& q0 P9 ?! ?: d! E
TIM图片20170928215619.png
5 [- M1 Z% N0 ?! u) G5 q8 ^" ~此外还需要修改最大的接口数(好像2个VCP设置大于2即可)
: p0 l) u7 V) X3 y+ M因为USB库中使用了maclloc申请内存,要适当调整栈空间。
% c8 T) j) V; Y; j& I  m6 h3 T4 m1 s3 V+ l# }% U
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png
4 D& J% O" K2 E7 R/ d
4 h* a1 |% g! y/ N下面是枚举的过程和安装好驱动之后的设备管理器显示:
+ \: b( {3 S/ Q( R7 ?% S2 l' H$ Q7 G9 G3 W4 t9 i" U, R, M3 _8 r

, V5 n$ T( w3 L* ]5 B  v b1c85265-21c9-4197-9d29-b539741de625.jpg 9 {& L* U5 U7 ~1 M0 j/ R, V* m
5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg
! T8 q% v7 w( S5 [! i
3 U" R! t0 @1 V2 ~8 s
1 E9 c* c/ n% t, v. o9 } ed917e76-1d1c-4323-8bbc-dccf431f929a.png + F' A/ {  z+ L3 L* i( J" t# j
+ q  D* o1 s. a0 }) D& D( J

4 z& X' ^! p& L0 m2 e9 O7 x( t, i+ t测试代码如下:: W, q, Q0 n/ O/ C1 V$ _/ C( f
  1.   while (1)
    6 |5 C: F- x+ ?& w- h: V! _
  2.                 {3 m. ]5 v# d8 B, d, G
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    1 A! c: |$ q% i: h# T& ~& ?
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);) K% i' |* G1 N2 _, w
  5.             HAL_Delay(1000);
      l0 T" B! V/ z2 R' u3 M
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    4 t4 j# f0 Y  W! p4 T( K
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    % Z" B% J$ c. p+ v0 Q" d
  8.             HAL_Delay(1000);      
    ) _/ X7 |0 k* q$ x+ g' S
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图)
; }' i* g( T: K test1.gif   o) T" q1 ?4 C

% c4 B9 t# i6 V* c8 }0 W! \
9 [- D1 H( o6 k0 L( R: s# U1 M具体发送方向为:
' L$ B5 {3 |/ d% E4 S4 j9 x* |) d/ F

# d  Z% O  f& y% N! k a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png * m' a# X' V8 R- t) E2 ^
, \0 h9 W' a+ X' g0 ^# D6 l
* k; f. S* n0 {4 h. r# y
2)、3个VCP串口,: `; M. k' C$ R( r3 F- b" r
! h9 `3 i; G3 c( ^. i. Q* P. n- R
在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
; e" G8 n! w) g$ f- }8 W) ^& O+ c1 h- d# e$ |" d$ A4 f
d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png
; R. z9 l  q& u! {. F4 l5 k- K" F测试代码如下:* z7 m2 ~1 \) H1 X, d( R
  1. while (1)
    $ Y/ r) _) s) C- g) V
  2.                 {: f6 V  [5 l- I  r
  3.             memcpy(TestBuff,"This message from VCP0\n",23);0 t) n/ d' L& m8 P3 G
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);$ F; h- p. x! c4 B( _6 M
  5.             HAL_Delay(1000);
    % J3 S0 ]( m( Y' I& B- M- Y
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    ( C0 m: Y, o9 G- y, F
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    + n+ \2 i' |+ p  p( A* ~! i
  8.             HAL_Delay(1000);     
    ; z) N" D$ p) u* \$ q8 F3 V) _
  9.             memcpy(TestBuff,"This message from VCP2\n",23);
    " f: r, x( u! n
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    * C  d( ]0 C$ I- X) b) B3 o
  11.             HAL_Delay(1000);      
    " I9 D0 p* h$ i
  12.                 }
复制代码
; _0 |% U4 b  Z5 Y( I8 ?

; F" H# }% v% q. @$ QUSB收发数据测试如下
(点开查看大图); d: x8 ?0 h) X9 z4 O
test6.gif ( r5 b5 h+ V- R: X$ n) f

' I9 }# l2 M2 Z. g# v 373b1865-5fcd-493b-9972-f02d2b90dd98.png / X! e7 r5 W) [$ B

! L- ~& b* t' i' a5 G% p# t2 、驱动INF文件
  R3 u, D4 Y4 l- e; Y& y# F6 C- L0 z6 j, y  u
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。- \% }' j+ }2 g2 l0 i1 f) M8 ]
- _$ j6 ?3 P/ @2 }. V  @
测试代码:
5 T  v- E/ m7 A) v/ i- d  e7 X
: d, A( k# s0 O4 K& e4 Y 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
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:9 s+ D' r( i& ?. h8 x/ j
endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));/ x; d" y: z8 W: V
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
( }# A0 z3 L$ n' K( t+ Q' Zendpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));' F( L; F6 B* W$ j
就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错3 n* v% Z9 D, i3 J1 e
      /* Prepare Out endpoint to receive next packet *// C& G2 G  [7 x8 Q9 u9 K; ~
      USBD_LL_PrepareReceive(pdev,6 o1 N) f9 M( y) d' I6 Q
                             CDC_OUT_EP1,. p1 k9 |0 c. S/ p- L( \
                             hcdc->RxBuffer,. Z% w, n5 _# T
                             CDC_DATA_HS_OUT_PACKET_SIZE);+ _% o) G% A' c$ p0 l
! Q" v  R, C- k* A/ H
这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:351 `( I. @& P! ]5 ?9 g( e
现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...
3 w% @8 u: c; y2 G
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。
7 U& c: H. s3 `2 Q2、没有数字证书的问题我也搞不定,这个目前没有办法,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
4 r/ b$ R. V' \% o2 P0 M版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
* ~9 L& E% l8 M+ D, B# T8 H
可以先了解下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:521 x& o0 y( i. ]- k0 y8 t" c! U( s
可以先了解下USB复合设备。
) m7 q0 {9 S/ _( p2 C' ?* X
好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:52
) m  k3 ]8 k/ P0 @5 }可以先了解下USB复合设备。

; N0 U, L( e4 Z好的 !!!
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
膜拜~
% }  O! H! p/ }4 ^
* `6 s" ]* w1 P谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55
) b( I; L4 [& T5 K膜拜~( W! B& |) ~$ p7 U- s/ x# o
+ [; g1 U+ G8 n) h% j  H3 O8 O7 H1 p* w
谢谢大神分享!!
% R1 A; @9 P" K6 \/ c  S
感谢飞哥带路!
wofei1314 回答时间:2017-10-13 09:36:15
又看了一遍,好详细!!!
唯有奋斗 回答时间:2017-12-30 08:58:42
您好,请问一下STM32F4能虚拟出几个VCP呢?
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版