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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑
4 g+ L2 b; a  `2 K; M) d' h" D# I6 _! H, s

& c1 Q4 U  C( [' M         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
* \, A+ o7 [. {* g. t& d: E; g0 z( o6 L! [9 w; a' E  i
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。
4 W5 Y* y, r5 [$ A8 S. t
* i* l; w7 W! M& S4 S4 O, R# I
9 t( C. G' v) N( h! O* ?& D6 Y, _1 w1 `
0、复合设备% L# v% V: t+ ~
5 A* h% k" k: g

* q7 q9 x# r) a  kCDC 类设备在枚举过程中最主要的信息存储在配置描述符内:4 C. v; p4 d# ]8 ~/ c
* f5 c. B' Y  k+ F2 ^- t8 ]& X
* T% Y* N# P* N8 Y; f: L. i
abfdf189-a154-49fc-bd00-ab9c51382987.png $ K5 o% m0 g! y# Y7 U0 n3 x/ m% N
3 n! D) K7 I% s
- Y, Z6 G3 ]- T  c3 H2 @
  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
+ Q3 I( e+ z; x7 D3 z1 E和使用的接口。
8 m7 t1 m6 r- d% @2 k# p  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。1 N  j' F, P% z. l& e

% s- B  ~  J% h4 K$ [5 t3 F( @1 Z9 z9 w" ]& l( G" I& _( E" b$ v
1、USB库修改; e: k6 n0 X) n  \" G5 Z1 }

# h. G7 T' ?: u! T+ W2 K  R
" J6 U( d; Z) u
: r/ m" x- A' w' O! M% R不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO
$ H/ a0 ^$ C) L( s& f上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。5 x( o) z% y: g0 w& [/ W# [
, ]( O# F& b/ \7 g6 l) W7 n
1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:
% F4 F# \% [% G( N
2 u+ O2 h# |; V) V# r8 O, J 5ec90026-3c9b-4786-87e0-06cadbef4265.png % k' |* C: E4 W4 s* D1 }
9 C' [/ @+ T0 x

5 t, ]: r) Q! ]0 Ba)增加端点) Z1 I/ E. u3 E7 b, X& b
一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。3 K2 [4 o( u, Z  T- i/ O

- T6 y5 r! S% o% A$ l; T 5b8ef82c-10a1-4d37-946b-ae60da254152.png 5 R$ Z/ D6 ^9 d5 U0 i, O% y  p* ]

2 F! y# h% b0 Q& O1 x. a) q" y设置增加的端点的FIFO
# V. P$ @: a3 P# S( [5 Z6 ^2 S- N! x' h3 }

+ l5 l* R3 f$ V 0ddf6de2-e026-485b-8070-04514e83e56c.png
2 H) a& a6 q  v, r' L
$ a3 B* i6 M5 Y0 p, @5 q4 }9 [5 _' t' G5 W/ U( [
b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口2 @$ A1 w; T* q0 i. c: ]
, D0 Y2 t: l+ W5 a+ {7 \

$ J/ y/ r1 D5 ~. e! `9 |- N+ c7 x 48c4af14-a790-4617-8015-6c8f1131cdd4.png 0 w: e8 w. m8 o" o( a
) Z; t7 a" c+ O# |: T6 Y
8 O/ Y0 S) u; Z0 f* B  ]; R
c)将设备描述符修改为复合设备模式
0 z0 E( s( d  Y) p4 t1 i1 I1 a4 U7 g9 b8 L4 R% I
  A4 M. [0 e0 N7 ]
98db37ba-b3dc-45be-b228-1590afb41c85.png * r" I+ ^4 k7 c$ i& ]0 M% f
1 p1 M3 w6 S. L

3 b" Q6 k% Q# {) K/ L. ud)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组; o! p' m4 \( g
& z1 I+ S9 }+ H% ?' t
TIM图片20170928215619.png
$ F/ Q+ \; _' l8 C4 z: I& @' b9 I此外还需要修改最大的接口数(好像2个VCP设置大于2即可)4 t7 P1 \+ L" h; [' J
因为USB库中使用了maclloc申请内存,要适当调整栈空间。
3 C* g+ U# l- B/ o- \7 M& a4 s7 ]3 [, B; l9 j% S
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png . [' k  w" T& d! c& P9 a
8 g* f8 T, D8 Z" T
下面是枚举的过程和安装好驱动之后的设备管理器显示:: J4 L8 H/ N7 }% l
: n; e/ k: x* I- s
( y! f4 `9 ]3 {+ j: _8 U
b1c85265-21c9-4197-9d29-b539741de625.jpg
$ O( s1 N# G! P0 y3 o& E 5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg . ]6 N5 X) B* M" U4 s3 @) |+ ?. g

8 n/ j! k3 S8 L# U; Q
7 l( [* n! j, _% R( T ed917e76-1d1c-4323-8bbc-dccf431f929a.png * L  n, ?3 i0 `
/ M1 M. X! ^0 m* s

( x0 S7 ]3 @1 s, k测试代码如下:& Y; Z; }2 A0 c# M7 y- {* u
  1.   while (1)
    % W5 g( V6 @; p2 m( a! h
  2.                 {* D9 u3 z2 y# a
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    ' _% ~# B5 [8 u" a& h/ ~: }
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);% r  q9 y% F, l1 E( I
  5.             HAL_Delay(1000);
    3 }, V7 V4 Z8 k/ l9 M
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    * n- {' N+ b0 m
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    - z, I$ {. r/ {) v
  8.             HAL_Delay(1000);      
    0 g! B4 ~4 R# W, z' d. y( \
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图)
4 @, B6 A3 y9 ^6 F$ ? test1.gif 0 D9 l8 T: `2 l( z0 a6 O7 a" N) P. S. l
( S  n- ]5 r3 K- D# i: t1 v6 H
% {" w1 i+ B" Y/ \  ?
具体发送方向为:- {. h. I% Z& W. z/ M. b
+ x' G" |  N7 q2 [7 W

  B$ }# k- U& o+ x2 R. A2 o a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
  E2 j/ `: ?# o5 b/ d( X+ F" f9 j8 n% H6 d$ G) a' `

7 D3 I; f" r0 ^) q2)、3个VCP串口,
5 X9 G) r0 f3 y" {
( F7 `6 l" G. P4 y6 u( t/ u在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
! o) j  Q, z8 Y2 J* D8 _5 ?: E" q; C+ b" z- Y0 K( @
d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png & ~# q7 v# t- F. m: y" Z! D
测试代码如下:
- a; x% p( |! G9 A
  1. while (1)& S  |+ j2 w% ~
  2.                 {+ n5 P$ V, t. h% f
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    1 A8 N* x2 ^% m6 U: t
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);
    0 Q3 i+ j# x- R5 R  V" a
  5.             HAL_Delay(1000);
    3 A& Z- O, F. I8 b; v
  6.             memcpy(TestBuff,"This message from VCP1\n",23);
    2 U0 l5 k, Y  ]3 `- K7 S& y
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);4 G# l2 X$ |# Y
  8.             HAL_Delay(1000);     9 _# C) d# R+ U9 V3 b+ j8 ^
  9.             memcpy(TestBuff,"This message from VCP2\n",23);
    9 Q+ m( @* A/ C. U3 x
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    2 O- X8 o6 i/ U
  11.             HAL_Delay(1000);      
    3 R% t9 g! ?$ V8 i7 k  d
  12.                 }
复制代码
; k, G. n# z6 u6 P
6 J5 D7 H. f  K# d. v$ n0 z
USB收发数据测试如下
(点开查看大图)0 }. }: c4 g* d" F4 U$ Q+ c& [+ J
test6.gif
% i- c/ N3 Y; q
2 P2 M% A9 O0 v% [ 373b1865-5fcd-493b-9972-f02d2b90dd98.png
% |8 L; @& h( F6 o. `9 ]' h4 G( H
2 v; r; K3 T' |5 T2 、驱动INF文件
* _6 w& A5 J, m- y9 \( l' {# n
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。9 T9 U% @3 p: p7 X$ f
1 r& d, n, y0 \, @
测试代码:
' X% M' n2 n$ Q* ^0 S
1 p4 |) b6 Q# s) l, T6 p 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
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:
8 m- w# C' H* j' j1 m+ [endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));# R! X% [9 @% ?* g! m& |8 m& l
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));7 J! `+ J9 K* B/ t5 O& S
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
4 `: E6 f. x" X6 y就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错* ]0 \# ]! M% e# a, n. u) Y
      /* Prepare Out endpoint to receive next packet */$ }4 V1 F. A$ b( L1 k4 V7 }0 C$ r
      USBD_LL_PrepareReceive(pdev,
+ o' X7 T; j1 P% Y                             CDC_OUT_EP1,
1 v) J" Y7 P# a                             hcdc->RxBuffer,9 M' U# ]7 v2 y% U' w
                             CDC_DATA_HS_OUT_PACKET_SIZE);
1 p2 p+ p0 c* S: w
) F" G2 i/ H& @: J( R) h) n这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:35% u# g1 t( I8 c1 F" Z
现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...

# f7 a# n0 m2 W* d1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。
- [1 @* n4 l2 H( ^. w0 J2、没有数字证书的问题我也搞不定,这个目前没有办法,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! M3 x5 _# ]  Z& W/ z3 f
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
8 ?# q! i( ?$ ^6 h5 N2 t! I1 F3 @
可以先了解下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" r/ @  s2 W1 g5 s/ `
可以先了解下USB复合设备。
( D. C& M6 t# y. K2 B
好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:529 F$ _  {6 o% C- o* p
可以先了解下USB复合设备。
1 \' U* T/ ], c7 q9 H- [
好的 !!!
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
膜拜~
6 C5 S# }; l& E' ]5 T$ u  i
  [" ?3 Z5 T, P$ R' l谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55
, P. [; V9 e0 t# T膜拜~4 ~3 Q1 b- q. S6 i8 F0 U

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