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

STM32 USB CDC 虚拟多串口  

[复制链接]
creep 发布时间:2017-9-28 22:30
本帖最后由 creep 于 2017-9-28 22:37 编辑 7 C0 ^3 e) u  u, |6 ]
/ z$ f# m  {, G( d* S* H
% M, ]2 d  U; z) K! @" i4 ?
         之前一直使用STM32的CDC虚拟串口和上位机进行数据通信,通常只枚举一个串口基本就能满足要求。但是STM32 USB提供了足够的的端点可以在需要的情况下枚举出多个串口供使用,最新跟着论坛大神飞哥  @wofei1314 玩了下多个串口的使用,然后我在STM32F769-DISCO 上测试了下多串口的移植,以便以后使用的时候可以参考。
: m% T+ O+ h' W. @4 c1 x5 F2 o- K9 ^
         关于USB的使用ST的库文件里面提供很多的例子可以参考,除此之外官方也进行了不少USB的培训,没法参加的小伙伴可以看下培训的文档对USB有个基本的了解,然后找个板子把USB库中例子都跑一遍看下代码应该就会有个基本的了解。* L. X6 [. c9 }
, h  J: ~, k* U: Q, M8 |: M

8 A! j. m; c9 N0 k4 ~! J
' R1 i' |, u' q' y 0、复合设备
$ Y$ O5 B9 t; w. \! W8 F4 e
+ \, Z! A& X" M: v# n5 f  i9 A3 ?) i. i' k7 E1 }& M& k
CDC 类设备在枚举过程中最主要的信息存储在配置描述符内:: a: P( V, E; z6 r+ D

" P" \) F" i% l* k0 C* Q$ d( H. B! E( D
abfdf189-a154-49fc-bd00-ab9c51382987.png , V4 D: W/ P. k# e  L* x. b7 [
! n2 V0 ]& k; ]6 D; M6 e- S
, N1 o9 W9 R+ S
  如上图所示, CDC 类的配置描述符一般包含两个接口 (Interface 0),一个控制接口,另外一个是数据接口 (Interface 1 ), 除此之外,还有一个虚线指向的 IAD(Interface Association Description),这个表示这个是不是可选的, 得根据实际情况来确定其是否真实存在。我们使用的CDC多串口要使用到IAD进行设置,通过IAD可以设置相应的接口枚举的设备类型" l$ M/ {( c( v. v8 E
和使用的接口。
# ]1 f2 |, J. k  一般来说把多CDC 串口 叫做复合设备,和一个CDC串口相比,USB库要把设备描述符、控制描述符进行修改 ,多串口新增的端点也要进行初始化 接收发送函数也要根据相应的端点进行处理,PC端加载的驱动也要适当修改。  W% v8 }- k1 v0 ~: l* j7 ?0 S

$ E5 }2 z: X7 T! P3 ]8 ]
+ F1 e: R* w; S& x  ^  I1、USB库修改, l+ C% I" o) w8 p* m2 V% l

: W9 k. M- e+ P" o5 M; L5 {+ H$ S  `* B1 x4 _) m
5 ~$ w9 u5 j0 }* S
不同的芯片型号和不同的USB库配置可能有不少的区别,但是知道了需要修改哪里应该可以根据具体的情况进行操作,下面的移植是在STM32F769-DISCO1 t0 W4 X6 S) j
上由官方的HAL USB 库进行修改。默认是在一个CDC串口可以使用的前提下进行,关于一个CDC的移植可以参考官方代码或者使用Cubemx。& H' g% X0 d% o' {
: _8 q! p, L$ b9 c/ L+ C' [( |
1)、2个VCP串口移植是在可以枚举出来一个VCP串口的工程上修改的,主要集中在USB CDC模式下的Class中文件及相应的头文件:) i1 {, N& ]- ~! h# H: Z

0 Y* z. X, U: c+ V7 N 5ec90026-3c9b-4786-87e0-06cadbef4265.png / S. `; a1 @! P! ^8 v5 m& ?& a
( W! Q) _/ Z' F/ b

$ s: Q) V2 t$ C+ ?a)增加端点
6 K9 K" l; F5 ^% D+ G# _; P) m 一个VCP的时候使用3个非0端点(2个BULK,一个Interrupt),再增加3个非0端点用于枚举另一个VCP。0 ?" t: b  W2 w( Q* V
0 K) q4 m  f# U' C! ?& x
5b8ef82c-10a1-4d37-946b-ae60da254152.png . @/ k3 _$ H+ @/ a  v) S9 c
1 m  e* O% r* p; `. }
设置增加的端点的FIFO$ g) r& i0 R; N% \# e/ t5 G
. T: e0 I- G9 u7 u

  ?$ {7 g! G, P# M: T' Z 0ddf6de2-e026-485b-8070-04514e83e56c.png
& L% ]3 c. U5 N  C' n
* ]5 Z( J. x# q. I4 f2 o$ [. t( o7 X* ?- Q  m' L: _
b)对增加的端点进行相应的初始化操作,我测试的是STM32F769-DISCO 上面的USB 是高速接口
* I1 R, `* m' K! x' s* h% K$ A/ ]
, S- O# S1 `8 o+ O/ g0 w6 _; Z3 ~3 L+ B. {* Y* o1 q. w8 d1 s
48c4af14-a790-4617-8015-6c8f1131cdd4.png - j6 U3 L' ]8 {. s6 i. a( L

% C! X$ U! k+ u8 E7 k; H& b, K# C5 ~3 C: e0 i. ^9 ]
c)将设备描述符修改为复合设备模式
+ p, {- ?# X* n6 X, l+ e  ^* W
7 [2 Z4 H% q0 [! z7 V* h6 h  k/ D2 Y7 j* F% n! n
98db37ba-b3dc-45be-b228-1590afb41c85.png & S  N0 y. ]# F+ q  i, _

, ^) c9 o" L6 X. y0 D9 z! P. U4 [% B. W! G/ E9 H$ L1 F/ {
d)配置描述符,注意我使用的高速 USB模式,如果是全速或者其他速度模式选择相应的数组; ?8 l5 u' {- Q8 K" V

; @% W) h! G& z3 {& h: f( H0 p9 } TIM图片20170928215619.png
5 G( i6 L/ N- O# s0 y1 ^1 ~此外还需要修改最大的接口数(好像2个VCP设置大于2即可): Q4 k, d& G7 T: S8 d/ \/ c6 Y1 ], F
因为USB库中使用了maclloc申请内存,要适当调整栈空间。
. r# S# s4 w& {7 B) @  b, q; {% z6 f; P' \; b$ u+ k7 v, d& Q, x
2a0963ce-d11f-4a48-aff2-f502028d0e1f.png
7 C8 ~# U' C) U; Z5 f2 }5 d- N# f6 Y4 w
下面是枚举的过程和安装好驱动之后的设备管理器显示:5 Y1 [, s$ o. n/ ^9 B: R* B

9 h- P$ r# v5 q8 ~1 X5 W
0 E* q8 P- T; |8 ~# P b1c85265-21c9-4197-9d29-b539741de625.jpg
% I/ d6 N, s( p! A9 F 5294a9d3-f04b-4c63-a85f-e3edd6e56495.jpg 8 ?% O( Z. c  \; \( E6 Y* x
) o! F/ u1 D" N9 |* O" V

! c8 y! {2 n2 o" M ed917e76-1d1c-4323-8bbc-dccf431f929a.png
2 w7 P' O/ V+ W6 [# J; m
  u1 T+ \( [. a0 F. J  T  u8 Y/ S* l. A4 x* F: n+ `' @
测试代码如下:) n9 ~& Z3 k2 d' ~; m6 L+ f
  1.   while (1), G3 O: A2 L9 a
  2.                 {
    3 [' d& @2 L3 q4 w9 J) c4 n/ W  o
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    0 m/ e2 u* k3 h6 |; C4 s
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);; O1 `4 `0 M3 |( i
  5.             HAL_Delay(1000);" b1 q' P5 K1 V) w: b+ X
  6.             memcpy(TestBuff,"This message from VCP1\n",23);0 f" a. a+ c" ?6 U3 U& h
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);
    & S/ w  T8 H* Z- Y+ Y9 d5 r/ H
  8.             HAL_Delay(1000);      - O8 ?: ~+ I5 J
  9.                 }
复制代码
USB收发测试效果如下
(点开查看大图), ~  O- b: x/ P. K- `& V
test1.gif ) {2 _: _9 n- q0 m/ c, G. Q7 J  Y

3 A; G: `8 M; v0 G: d  W
- Z. m4 c- f- E- O( o具体发送方向为:
- t$ U$ b  N5 B  M  e! x
% A+ H3 L0 W( K3 r- [  G  M3 T: C( Y& H& P) i
a5af1022-17e9-4a9d-9f0f-d7efb9f29422.png 0 Q! `$ s; S2 V$ B8 ]

' s; @+ j+ m. J' y* y  S! d' h1 ?3 m5 T4 }6 _; A* P+ E: }
2)、3个VCP串口,
9 {3 m3 _$ J  w
6 X% G; e; q5 |+ P) R, a6 X在上面的代码基础上简单修改之后可以很容易的枚举出来3个串口
1 s. @: ]6 P. F/ p5 s
. f+ \& w) M4 }8 \' g  n d79eea4b-4d3d-42d4-b2ed-3c461a007d97.png
, U; x3 p  `0 X& N0 L+ V测试代码如下:
1 g3 [$ t/ c% x0 ?
  1. while (1)
    % k) C& L5 Q& T' o  ]
  2.                 {
    3 i) X4 d( g. S: e) i
  3.             memcpy(TestBuff,"This message from VCP0\n",23);
    5 y/ H9 |+ B* A/ |) Q8 }
  4.                         USB2PC(TestBuff,23,CDC_IN_EP1);. b! G5 f0 [( H! R$ m- I( r. h
  5.             HAL_Delay(1000);
    ' A" V% {! c  g- b# E
  6.             memcpy(TestBuff,"This message from VCP1\n",23);0 G% |9 d( P6 ]2 S1 M: L
  7.                         USB2PC(TestBuff,23,CDC_IN_EP3);: A( n' f5 W9 a4 S8 v
  8.             HAL_Delay(1000);     / C1 F. \! E% ?1 W
  9.             memcpy(TestBuff,"This message from VCP2\n",23);
    " ~. G0 H* Y6 g+ e9 M- q* |6 `2 w! }
  10.                         USB2PC(TestBuff,23,CDC_IN_EP5);
    0 s5 u$ @, c4 s
  11.             HAL_Delay(1000);       ' |% M6 k7 j2 d
  12.                 }
复制代码

4 P( R" v4 ?# O# S( q1 S
+ E0 E+ L, P, ^3 q- w/ @. B9 r0 @USB收发数据测试如下
(点开查看大图)
7 e2 ]( ]! {7 }6 w/ G: G; ~ test6.gif
6 N1 W6 W4 m2 s5 s4 [% w5 F- p8 W- Z1 B7 w* u! X. c3 T) t
373b1865-5fcd-493b-9972-f02d2b90dd98.png
! c1 s/ C4 e" X: O
; z1 {* w1 w# l. e. h2 、驱动INF文件
$ [' D; g1 I" X  ~# H! @( l2 c; v% @" |0 b3 C4 p
复合设备需要修改inf文件并手动加载驱动,此时要注意库文件中VID/PID和驱动里面的值一致。修改过的驱动可能会因为没有数字签名证书在某些系统上无法加载。如果是WIN10系统可以加载兼容驱动也可以正常通信。. g1 Q5 Y6 O" R4 _5 z( H( W) y* l
- \8 @' a& C$ V* C6 \/ P- S6 k
测试代码:
4 Z, @' S  M3 D  @7 |( E& l3 [3 L0 o! J2 P% e! T- ?/ N* `& q
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
你好,你写的教程基本都能理解,就是我想问一下,我研究的源码里,它没有分别对某一个端点进行初始化的函数,而是统一用一个函数来初始化:
2 y2 P5 s: Z4 G& Eendpoint_control_address = (UX_DCD_OTG_FS_DIEPCTL0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));: n& w5 }8 {5 i: C7 ^
endpoint_size_address = (UX_DCD_OTG_FS_DIEPTSIZ0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
9 `0 C' P. r7 O7 y8 g. D7 aendpoint_dma_address = (UX_DCD_OTG_FS_DIEPDMA0 + (ed -> ux_dcd_otg_ed_index * UX_DCD_OTG_ENDPOINT_SPACE_SIZE));
0 l& U& s% q/ Q* [就像这样,在一个函数里就设置了端点0和非0端点的所有端点的IN设置,可根据ed -> ux_dcd_otg_ed_index来判断是哪一个端点,所以,相对来说,如果我添加了端点,就是不是不需要再添加我加的端点的初始化函数呢
深圳老刘 回答时间:2019-9-4 01:01:07
还是不行,感觉大神的代码有错
2 x# W) ?1 a: ~. |. Z      /* Prepare Out endpoint to receive next packet */
1 u8 v5 [: p- R* ?2 ^# l      USBD_LL_PrepareReceive(pdev,
* P1 v) H; m: y6 E- X7 Q                             CDC_OUT_EP1,$ [# r& W. e. B' A: d
                             hcdc->RxBuffer,
* ~  L7 L" f7 [+ z                             CDC_DATA_HS_OUT_PACKET_SIZE);3 t: j' m) O) M

$ J2 P+ S: W, Y! c0 C# M! R8 V这里怎么处理
creep 回答时间:2018-1-11 16:06:23
MaggiGunner 发表于 2018-1-11 15:35
8 o' e4 _  @0 F1 U1 G8 n& ~现在用CUBEMX生成单VCP发送没有问题。我看网上说VID和PID也很重要,我在您例程里看用的是0x03EB/0x6133, ...
, B  R3 l1 z) b9 I. E
1、 要保证STM32程序里面的用PID VID和驱动文件INF的PID VID保持一致,这里使用和官方的PID VID不一样是为了加载自己写的那个驱动,这样可以修改枚举出来的串口名称。
2 b+ v$ c- y: E7 i2、没有数字证书的问题我也搞不定,这个目前没有办法,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 w* s" w& T. {) z, m1 V版主,能不能直观的给我讲下,为何可以虚拟成多个串口,我一直理解成只能虚拟成一个 ...

" p3 L# H2 |+ T" U7 w可以先了解下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) d' R) P- C6 O$ B0 c% A. [- V* `
可以先了解下USB复合设备。

' K) H$ {" _$ D6 j; V好的
gujiamao 回答时间:2017-9-29 11:13:41
creep 发表于 2017-9-29 09:52
, K9 N" m! H2 [* h可以先了解下USB复合设备。
9 V* J* N7 }. W& m* J
好的 !!!
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
膜拜~
1 B% v8 r& t2 p: A4 I' S1 U# ^# e, R( c0 E1 A
谢谢大神分享!!
creep 回答时间:2017-10-11 08:50:29
wofei1314 发表于 2017-10-10 22:55) `$ Q& ~! u, s6 p! I! @, Y
膜拜~7 r1 r9 u7 ~/ B% Y' [% S5 \

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