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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑 " Z$ W3 G( e& N9 |4 i- T% Z5 {
- d/ h. C* ?' t  N, |
- ]( x" S, h4 j- R0 \1 v* P
         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
: F5 l  I% Y, j6 X6 |9 C5 C0 E2 Z
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。
$ A: v! n8 G9 ?8 x; ?; Q( C- x0 x/ M" M# K) `
& e6 O2 L, {. L5 @' L! B& g  X

$ F( T5 @& ~2 P 0、复合设备9 C0 P( _! q0 z3 P

$ U) L! H+ e3 {; W" Q" W0 T
6 d  \0 ?, x& J$ lCDC 类设备在枚举过程中最主要的信息存储在配置描述符内:
  ]1 A8 N1 ^0 d8 r8 j) @, Y2 P% J  B  A# G8 J- W. ]

" |; A/ `% m$ ~ abfdf189-a154-49fc-bd00-ab9c51382987.png
2 q: r# S( g7 i$ g5 j) `+ F$ |7 |8 Y0 W- B+ g2 d

# D7 L! r7 K6 ?4 O' t* E" G' h  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型
: t  E7 V1 g  U0 p0 m和使用的接口。
/ K) P7 u6 ^' e1 y3 R' @  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。+ K% f( ?, B. u+ t! ]
) f2 [; A& p; V+ S, F9 Y( Z; C8 K
/ g3 n/ }. a! q+ @0 W
1、USB库修改
* n% H2 _. k# P+ W: B
1 M- r# u$ `# c
6 L% M* N( s3 F( k% _7 l. N0 |$ d* J6 c" E9 W. F
不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO
8 ?) }% J0 U/ @' |( ~上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。1 ~7 ^: ~9 ~0 F: v5 O+ W

6 N- s+ ?2 c0 `0 Y# t" F% K1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:4 ?" E9 y: Y4 h- r0 G

8 X# |& P; c. \& Q' w 5ec90026-3c9b-4786-87e0-06cadbef4265.png 2 q) y  M1 t' G* w. C

( D/ [7 q* o  a8 e; [; e9 G$ l5 z% d
a)增加端点+ s8 r, l7 [( }, T5 G$ e5 i# _
一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。/ q* C- F. v+ D2 \; f

; R7 ?3 l1 l% V0 Q( ?' } 5b8ef82c-10a1-4d37-946b-ae60da254152.png # R$ Z( [! Z6 j" G9 s, W
/ \/ ]1 ?* b1 F
设置增加的端点的FIFO. b  h! g9 E: f5 X: n; J

1 V; B2 n3 y. o% I; f' K) P- q' j5 B6 N: K
0ddf6de2-e026-485b-8070-04514e83e56c.png $ M3 s7 n8 z: [) e# t1 O* c! s) `
+ z3 S2 q) n/ c3 z  F4 L
, G' x. |  M$ p( B
b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口
9 k9 p; f0 n8 u  M2 b! o# R9 H: B' c) [5 v7 h* B/ L" ~* S

$ a( O) m2 L# G5 q 48c4af14-a790-4617-8015-6c8f1131cdd4.png , g6 O2 p9 w1 n! W- L- l8 Z
* q  p5 ?5 b$ j2 `( D  ?
: T% P: L2 |9 W* c' c" V
c)将设备描述符修改为复合设备模式
* u8 L. U: K, q' t' @5 z" G1 M" A. C

. }! o! B' y& S2 q, R$ \' f 98db37ba-b3dc-45be-b228-1590afb41c85.png 6 l6 B: l0 w# D

( w: P5 i1 v( {9 R0 b& f& v; ]; ^0 w2 s8 a
d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组
% a  ~4 e' s' [( J, b+ O. V' {4 x: T0 ~1 i
TIM图片20170928215619.png $ L( C$ f/ U# V; z/ O- f. U. v
此外还需要修改最大的接口数(好像2个VCP设置大于2即可)
/ e) A' B) w, w' ~& W. L6 |$ P因为USB库中使用了maclloc申请内存,要适当调整栈空间。: [% G9 w0 z: u* h$ {; ~: E) Y' A

6 Z( Y" C+ ]' R& K) }- {6 a 2a0963ce-d11f-4a48-aff2-f502028d0e1f.png 2 k1 u& ]9 [- @9 W+ [5 M
6 L' ]" I+ Q$ t7 }, F. R4 b* @$ \
下面是枚举的过程和安装好驱动之后的设备管理器显示:
; W" _" x/ _- H' B. ^* I0 q1 R- \$ W

0 {- {- U7 ~  ]% ^0 Y. ^; h* O; } b1c85265-21c9-4197-9d29-b539741de625.jpg
) v3 r, O' t( O 5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg
/ r$ b* J3 N; x3 A2 W, I, R' M; a2 P' k' f' x) e8 x
1 n, q7 U: x) F" [. z3 O5 ]" V2 f* q
ed917e76-1d1c-4323-8bbc-dccf431f929a.png * H% F( M) A( F- {  C' S5 n  M

8 V' a0 j2 E+ c! H* ^
4 x' [1 i( o& d$ z测试代码如下:3 h% D: x; L! C9 c8 U6 m" Y
  1.   while (1)
    4 X- l) R6 w; _# c6 a9 L" f! a
  2.                 {' K. K2 J- [( T, C
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    # q% r9 W$ z$ D, A' W+ d) I
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);
    ( W. J9 I) N' F. S: D/ ?# ~2 n3 m3 a9 {
  5.             HAL_Delay(1000);
    " F5 D( n& p# W
  6.             memcpy(TestBuff,"This message from VCP1\n",23);/ q5 u) J: _% k" }3 r
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    ; ^4 V  g$ l* P( m1 G
  8.             HAL_Delay(1000);      1 A7 F$ @( H/ i- H  ?
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图)" s% l+ B" l5 Y% E% N9 _
test1.gif
" x9 {6 N" h* O  t
( h, B9 O, ^, p- Y( Z( X
. m- ^7 ~7 ^* `% O/ }) \* D. F  E具体发送方向为:
) ~# D1 Q( l( D' Q+ k+ g9 |5 M0 H; I
, c! D  k! k, j5 g" {5 @
a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png
  d6 e4 x, C9 ~9 w. h: ]# d5 ]9 k! O' C8 Y: e3 Q- m

! D( `8 H4 d4 l$ X# P. v2)、3个VCP串口,
4 }; C6 d% d8 ^5 |: W4 o+ s/ D
* k+ A/ P9 O3 [, w7 ~7 s在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
' v. g. h( G! q& P) P, E
2 `& W9 T0 [! [6 h) [ d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png ; C1 D% G0 t& ?/ Q/ f3 g7 p
测试代码如下:
6 v% W5 i: w  ?8 A- k# T, r
  1. while (1). |% U2 a2 ^/ W
  2.                 {8 P( c! G4 ^, p$ d% D
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    ; M+ H' m0 z8 Y3 Z: G8 p
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);
    / z: u1 F' S) r/ c) I
  5.             HAL_Delay(1000);
    2 D1 C9 y) S1 L" ~: Q/ U: {8 |
  6.             memcpy(TestBuff,"This message from VCP1\n",23);& r# f/ h/ M" R3 y2 c
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    + u  C9 w. }% Q9 ^! Z/ L9 Y' m, I/ r# ?
  8.             HAL_Delay(1000);     
      K: T2 M, ]! I* p6 z
  9.             memcpy(TestBuff,"This message from VCP2\n",23);
    2 j5 a* k6 f8 P" c( J
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    * \9 ?; l/ L2 {0 o8 R: {
  11.             HAL_Delay(1000);      
    ) Y$ @; k% Z3 B0 ~+ T# e+ i) C1 |
  12.                 }
复制代码
6 n! t% f* Y9 Z- w* h% ~

8 z0 Y/ e# t7 P, F1 B& iUSB收发数据测试如下
(点开查看大图). \9 z  y9 P. \. M. v
test6.gif 1 K0 e1 ^8 J& e% s6 p

. D! k% X+ Y1 B+ ^0 _ 373b1865-5fcd-493b-9972-f02d2b90dd98.png # _' C% _7 B1 I

9 t& F/ I+ r( Z9 |2 、驱动INF文件# S2 J7 k& b! S5 p* d

5 i# b& \1 l: K; A3 ?$ b: D 复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。
4 \' {, d6 {5 X$ P
# d2 _1 y. i2 i  \- y测试代码:
. P% u& Q& ]9 v  i7 j+ y% g. l; j  g! S# q. y; y( u4 @5 k* B; Q
Two-VCP-HS.rar (1.19 MB, 下载次数: 1848)

点评

厉害,研究得比较深入  发表于 2018-1-11 14:31

评分

参与人数 5 ST金币 +73 收起 理由
零壹 + 1 赞一个!
kylongmu + 20 很给力!
g921002 + 10 很给力!
wofei1314 + 22 神马都是浮云
zero99 + 20

查看全部评分

5 收藏 53 评论134 发布时间:2017-9-28 22:30

举报

134个回答
wylew 回答时间:2018-2-6 09:25:22
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:; q9 O  r; o7 z7 s, A8 l( N
endpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
4 ~4 d* w; h: h+ H9 K* ^% ?endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));0 M+ U; d/ ^: V  V+ e1 w7 q
endpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));0 \6 U7 P- s; c3 Z
就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错8 e7 o/ E8 o/ G
      /* Prepare Out endpoint to receive next packet */
. W" S& [' T. }      USBD_LL_PrepareReceive(pdev,8 X( J/ [6 [8 l8 N7 J" Y: ^
                             CDC_OUT_EP1," a1 X. z, z, g9 l" t0 A
                             hcdc->RxBuffer,! d: r( @7 N6 L( m" N3 r
                             CDC_DATA_HS_OUT_PACKET_SIZE);5 r$ z: h7 {, |2 v  h; e
- Z# b" ?4 V# t9 d
这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:35
- h* P5 W. \; r$ n现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...

# B$ x& X" [- ~$ _1 \1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。: C$ u5 h: F# L* \! L7 D
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 U% a" u% o8 }: P, @3 g
版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...
4 j2 n0 @3 ^% y% D. A
可以先了解下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
6 s6 Z' n( @' h# Y! q可以先了解下USB复合设备。
0 a" f! ^. t2 V; |8 b2 d$ u
好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:52
' V9 O. u  t5 w  z' p可以先了解下USB复合设备。

0 b! a% q; B( u7 [好的 !!!
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
膜拜~
- A8 e( X* N5 K1 A: p6 ]7 y2 H- f7 e  k2 {+ V" M
谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55+ P+ O# u: X6 m
膜拜~8 ^9 ]* B6 `/ y8 K& W7 H4 b
1 j* L3 @& z* B( s
谢谢大神分享!!

- z) W$ P9 j& s- f; B感谢飞哥带路!
wofei1314 回答时间:2017-10-13 09:36:15
又看了一遍,好详细!!!
唯有奋斗 回答时间:2017-12-30 08:58:42
您好,请问一下STM32F4能虚拟出几个VCP呢?

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版