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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑
% U) p9 Z# l- b% h  ?# a" N& T3 S- _3 Q9 U0 Z3 d0 r! U5 p
; |* k# _4 j& o' l, L. w
         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
7 U. V- O3 f, T" U" l
$ p' K9 N; }2 Z. h. I5 F         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。% i( {! J# K# L! k7 w

# G, Z. N" {5 A7 D, n  D, Z  i$ a9 ^3 [' n4 @6 r

7 t0 ^/ m2 W0 u 0、复合设备! W: q1 s  j0 H& @

7 `" I  f5 B* H4 F; c
* [( B! \, }1 ~5 U# P" ]1 yCDC 类设备在枚举过程中最主要的信息存储在配置描述符内:
9 Z1 ]$ U9 A8 ?5 J+ P4 N: T: ?# R4 s% e. I7 x  ?. i4 t

7 ?8 `4 Y" \( [! N' O abfdf189-a154-49fc-bd00-ab9c51382987.png
$ ?# q# \$ W: b/ _. G
& `% g3 N# ]1 x: q5 _
: t, J: n! y' c. U: z  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
+ P0 o% |  d( y4 a4 e和使用的接口。
  [8 I# p, T+ c. P* Z% ]1 v6 {  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。6 G- r# s9 |; F9 g

, e' G8 r& }. \7 e$ m$ ^/ d4 N5 E. E6 [
1、USB库修改( y8 ]$ P. Y4 O7 S8 r. ]) e

+ }) c" k  ^6 i* [- f; o5 e5 \4 ~6 v9 I! _  i1 k+ Y

* b- \. n1 D; i! Q& K" y( q不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO7 K9 b) K) J7 Y  T5 I; p, ~
上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。
% e9 o# f: _5 I0 e* W9 A  g. t- c8 \* i. T" i# [5 e7 \1 p# ^1 Q9 ]9 j
1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:( c; A+ N/ O; R3 B  o0 z

( j' I, D& V9 X! q 5ec90026-3c9b-4786-87e0-06cadbef4265.png 8 A0 C' d6 G2 K1 m  N6 _$ u( N6 K
/ R; f* \1 \6 b. O
. ~* ^# n6 f6 a! }- O# w
a)增加端点
. h+ a" s; A9 i6 k9 m3 R5 q$ J0 `! ?9 O 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。
1 ]# O6 G) A3 S* @( {
; ]* ?9 {$ p3 J6 X6 A) r" X 5b8ef82c-10a1-4d37-946b-ae60da254152.png
; Z6 N/ S- E* {& ?  ~2 }
2 u8 {" D: i( z+ X) _- U: f& R设置增加的端点的FIFO
. ]8 D; L5 g+ o, x; k5 j4 r, h( H3 a. W
6 M" b* R6 ?7 D; _: p! B5 ^/ [3 d
0ddf6de2-e026-485b-8070-04514e83e56c.png
4 |5 z7 z: ]  ~* T% F; P$ ?/ x: p1 p
4 Y: H  @  p9 I6 ~+ @# ~# l6 A( U) X+ Z4 l* o% ~) C
b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口" P/ g% }# x4 v' R' A% X2 N

/ n* n2 x% F/ [0 ^
9 ^1 l) N& U/ A% k, y/ }$ | 48c4af14-a790-4617-8015-6c8f1131cdd4.png 5 q5 H' j) k! p

9 K7 v9 N( a: k& y+ M( w1 l- N4 o1 ~0 b/ v; O
c)将设备描述符修改为复合设备模式6 W% D, g# ]- X& M  q+ ]! \

  h, ~( N9 f- X' }9 ^2 i9 ]" M/ e6 s, i6 d& T& ^
98db37ba-b3dc-45be-b228-1590afb41c85.png / o5 B; F- E. A) G  o
/ D* ~. y/ Z0 z, E5 C/ F

* o) F& g1 C4 S9 ~4 u. ^  Td)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组: e" W& @2 U9 d2 d3 h4 d5 q
5 I# y9 N9 H* `* V
TIM图片20170928215619.png + ^" A3 B# }; P7 {0 A
此外还需要修改最大的接口数(好像2个VCP设置大于2即可)
6 V9 ?4 X5 x1 ]# d' v8 t因为USB库中使用了maclloc申请内存,要适当调整栈空间。
* M5 ~2 D4 ?: h; q* E3 y' B4 ]
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png
6 `3 e/ H" Q7 a$ `3 |$ E9 ~  H
. j" c3 u$ j/ t: w( ~下面是枚举的过程和安装好驱动之后的设备管理器显示:
1 M- i" v' E+ V; I& l' @( e
) P5 J7 B% ]1 u1 S9 A- A3 u5 q4 R$ m6 b* m
b1c85265-21c9-4197-9d29-b539741de625.jpg
: b0 F% C8 H3 O; I 5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg
5 N. ]' ~, m6 _8 k! s
+ G4 R/ K; |5 g! H) f. F  E9 j" n% d0 M# w
ed917e76-1d1c-4323-8bbc-dccf431f929a.png
6 {. K; O0 ~* x( D! K6 O# x, G! H4 ?9 h" K, w1 x1 v4 [, Z
+ g) o4 M2 K9 m1 X4 Y
测试代码如下:/ q' ]0 C/ y* o/ I; z$ N
  1.   while (1)
    ! h. A' W, s" f9 [+ S
  2.                 {3 i; z. z( \5 x& G8 c
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    - _, p( {& |' ?0 ]6 s! U* j+ n8 T
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);) }- q' d; j& F4 l
  5.             HAL_Delay(1000);
    % V: D8 {3 p9 k6 a
  6.             memcpy(TestBuff,"This message from VCP1\n",23);% \$ u/ J3 C* `
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    ' k' j, z+ l- o8 ~
  8.             HAL_Delay(1000);      
    2 i# {4 J: D2 k& m' ~
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图)
( N4 Z, L. ?" a9 e& `1 ]+ N0 p( u test1.gif
1 H* g8 M2 n/ Y4 V4 M! S! [. T" ]0 U( D
, }, k& c% S7 w5 s
具体发送方向为:
" o  s* ]3 J' W' P
1 \. h  w4 V' G2 z. E9 A! w( b( t: n8 F- o: {* t* @
a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
$ ~. P  v$ h4 O2 v) t0 ]) [
, ?8 I3 V2 I$ v  E8 v! S
4 H* M& r) X' e: u* v. s2)、3个VCP串口,1 \4 ^& H, p+ y, t9 L

( K" X# j3 ~8 z" H4 x9 |3 B在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口0 q, G6 M& ]& g+ g

6 _& F5 l. A4 ~! w  z d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png
, V8 H+ `) S& `! N( _' _' N; c% a0 e测试代码如下:
5 x. v, w  }( W% E6 {
  1. while (1)
    8 _/ T5 R4 g! c$ }
  2.                 {" m1 U1 ?# I% d
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    4 c9 d$ e3 ?) B! R- z9 S$ }8 H
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);" L8 D: e* L( Z0 l
  5.             HAL_Delay(1000);5 p7 {+ i' j( k" j
  6.             memcpy(TestBuff,"This message from VCP1\n",23);2 ]" [9 m( Y0 e& b2 B$ L
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    ) M& P; v: s' s0 g
  8.             HAL_Delay(1000);     0 H5 W( q3 y; Z( k/ G
  9.             memcpy(TestBuff,"This message from VCP2\n",23);
    $ @; o' W* s! i1 l7 W$ i
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    + L7 u& @; a& T3 W1 S% ~2 {
  11.             HAL_Delay(1000);       4 b1 F. J) {! T4 Q' k- `  {  X
  12.                 }
复制代码
# w& P4 ~! H  u7 B' X  H6 @* l- F

; e, m$ n8 n6 _2 gUSB收发数据测试如下
(点开查看大图): j4 Z% a$ A& l/ F% v& x1 ^
test6.gif " }* R( n+ k( o; `

: R% y/ g& H1 T8 {; v 373b1865-5fcd-493b-9972-f02d2b90dd98.png
% V" S( U9 m5 s2 X2 E( }* N7 a
# N! ?: c2 o3 s- `4 r' Y: r! `2 、驱动INF文件. e, X. t9 _. K# x, l
; _; ]; ]6 N& [7 H* C! {
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。
+ v7 W$ b! V) ]4 g9 A! p2 b$ y0 `) s" t& D* q/ z2 A
测试代码:) K; S. m0 |7 k- s+ k. @# j1 S
8 Z7 G9 G) A! ^  W! _
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
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:% `3 Z" V0 m+ ]5 A
endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));0 X1 S2 q+ g/ J6 N) q0 K
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));0 j# l9 @5 s( q" V7 a" A4 c" w
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
7 p  Q6 M; x6 j就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错
* q/ b8 o3 h2 q" E! n! w! y! b: y      /* Prepare Out endpoint to receive next packet */( X" J+ Y" q0 Z# u
      USBD_LL_PrepareReceive(pdev,0 L( U. `: B0 K+ l
                             CDC_OUT_EP1,5 @) |) u. [9 F: T
                             hcdc->RxBuffer,
5 P. _" h+ ?' @7 I/ M# }                             CDC_DATA_HS_OUT_PACKET_SIZE);# t2 y; B( N7 Q# v; K+ E; ~

  C* ^' m! v9 G& g! E这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:356 p( ]& [7 w. S* u7 j/ |
现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...

; `* ]: Q' n6 g  C7 b  J# i2 J! M( r1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。$ q% B& h( [( {9 ^: f! 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:098 V- J. [3 T  q2 t) M, q9 i2 I
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
6 ?! f4 \! I- j4 d. m
可以先了解下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+ t% z$ }0 D9 E) e3 b& s; V% x' o
可以先了解下USB复合设备。
+ x- g: `/ }( Q- M
好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:52
3 k8 [  T" ]+ B: \( L可以先了解下USB复合设备。

2 q4 u$ d; s( F9 M! l! s好的 !!!
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
膜拜~
& n( k  {) W: |7 Z' B; a4 ^
2 U! k4 r# J1 I5 D8 P/ }' l8 Y谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55
" }: d. L* X% a$ K膜拜~
; E+ N: `3 p" c" `  p8 D$ Z' G4 o" A& r6 ]- X8 ?  `3 l
谢谢大神分享!!

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