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

【经验分享】基于STM32使用HAL库实现USB组合设备CDC+MSC

[复制链接]
STMCU小助手 发布时间:2022-4-9 23:20
工程试验环境$ h. c6 ^' a; j, b
STM32F103RC, C* \7 }1 e# _! E$ i" C. [
STM32CUBEIDE1.5.1
& P5 f' g% l) z3 N1、本教程默认你已经会使用STM32CUBEMX生成CDC代码和MSC代码,这两个工程的生成很简单,网络上的教程一搜遍地是。: j. r* N0 R0 T+ y: A
" N  p$ ?! L# S$ K3 x% d' B( Q
2、USB组合设备的移植修改需要具备一定的USB知识储备,如果没有强烈建议看一下我的另一篇博客:STM32 USB相关知识扫盲
- j4 m2 @2 X' ]: M; A  N! f6 F3 s2 _5 h; [
首先说一下STM32的USB库的初始化操作,MX_USB_DEVICE_Init函数中使用USBD_RegisterClass函数注册绑定了实际的端口初始化控制等操作,如果是CDC那么注册的就是USBD_CDC这个结构,如果是MSC那么就是注册的USB_MSC这个结构,所以我们的组合设备思路就是用哪个的时候,就将这个结构切换成对应的操作结构。
' R1 ~# `' N! t/ a% M& m+ u0 S$ a! z5 d3 {8 B: {/ i
第一步:基础工程生成8 ?, o& K6 \5 i- A! G$ o6 P
首先先用STM32CUBEMX生成CDC的工程和MSC的工程,并测试通过没有问题后,我这里使用CDC工程为基础工程进行修改成USB组合设备。
1 B' Q/ U. g8 _& ?. z
9 w5 Z2 Z( W* E) H# a  u基本步骤如下:: H) G3 W- p5 W3 ~* y8 @! d

$ p8 J- x0 j) o9 i3 j2 U( vUSB设备描述符修改成组合设备类型
  j3 |2 q" G' c  q7 d1 E修改PMA端点分布+ R6 D3 W" q& F
修改USB配置描述符并添加MSC的配置描述! ^1 b: g5 T* o1 D) l: v% c: L( w
修改初始化函数接口,改写成我们自己的组合设备初始化操作函数" O) E# s/ S. n$ J& z+ V8 ~( v
修改MX_USB_DEVICE_Init函数,注册成我们自己的组合设备" {- i. N1 ?: E& X* l! k
5 f" g2 F: K6 _- J

( c. n- d/ n% C7 U9 x9 N5 J下面进行分布修改。
' _! u# L2 v0 ]+ w: K$ y# c9 a' s
; ^) [; b, w6 n# L, [' L第二步:USB设备描述符的修改
9 B) A' x  M% q) b这一步很简单的,就是修改usbd_desc.c中的设备描述符数组USBD_FS_DeviceDesc,将设备类型改为组合设备类型:
7 i! u/ l5 X* L/ B6 w6 f$ w3 v9 L0 S( D+ h
J)4A6FO7U[S`S6NWUY9PT63.png : \/ O& k, [! K# M" ^% g7 S* p* T& M, ^

9 }5 m( e- x: j7 s第三步:修改PMA端点分布

* u' g/ J1 x% ?& n% V首先修改一下CDC所用到的端点地址,CDC的输入输出端点不动,将命令端点成0X83:
% `7 |" b6 \( @) @" A* M" `8 L& Y" i
% [* Z: Z, u! s- X7 u3 k( m6 }  p1 W6 X" Z/ O/ p
2HX(T@W6WV[XTC]MD)OVTS2.png
+ f( P& d7 z: k5 d5 P6 {& j' o$ m4 K! ^) H$ k2 g/ y2 M
然后进入usbd_conf.c文件中,找到USBD_LL_Init函数,修改PMA端点初始化:
* y' l6 u8 r6 t5 {: e
  o5 r1 r6 e0 O XEC{)J[~_964X[7EHLIV7.png , l  p: y4 O% ~  ]* A
, g8 w  I! K/ k1 i, i' k
这里的修改非常关键,为什么addr要从0X38开始呢?
" X; p% u; X- G1 n+ G
( X+ ?6 G. {3 H" P7 p6 {因为我们目前用到了:) E% T( u1 t# @, _

5 `5 i  t' `1 N: o- ^( N- s默认的两个端点(0X80、0X00): ]( J* U) z' T( }2 \1 w+ t) G
CDC的三个端点(0X81、0X01、0X83)
  ?# U' F3 y' C4 g7 O. rMSC的两个端点(0X82、0X02)% G' N2 Q- s& y% J- T: U
+ {) ^) Z; j" ?) u
' }; X% s1 n& z% I  Y% `+ y5 J9 C0 t
共7个端点,每个端点占用8字节,总共56字节,十六进制就是0X38!
% Y4 M# x! G0 D( W$ {0 D, O
- R9 t; I  b" d9 C& B  ?7 z好多人修改自己的USB应用时,就是卡在了这里!如果起始地址修改不对,那么USB端点缓冲就会覆盖PMA头部的端点描述!+ r) ]; \# c( h# B. e# \) v
/ B  H& F% f+ l( G- _
有关PMA的详细描述及使用,请看文档头部的《STM32 USB相关知识扫盲》链接文章!
5 }% I2 [4 z; [" ]% P
, H2 f7 }- S+ m0 N第四步:编写我们自己的组合设备配置+ B4 l5 g& A. R5 F5 j5 _0 n
这里我为了方便修改,新建了一个usbd_composite.c文件,用于编写组合设备驱动,文件内容如下:
4 o* B6 v1 u5 ?: o0 s8 p# Y
9 n6 g7 t# j* n
  1. #include "usbd_def.h"0 r) M4 W9 g+ d. ]* V0 @: t
  2. #include "usbd_msc.h"4 P8 i* o$ D* l: j% @. {( @, k
  3. #include "usbd_cdc.h"
    3 X9 j  J7 N  T: k5 k6 y
  4. #include "usbd_storage_if.h"
    ' j: X; }5 v3 r3 n
  5. #include "usbd_cdc_if.h"! f6 _- Y: V0 W( _: [/ D" r

  6. ; H2 a8 S! z+ j. f0 m" l: i
  7. 1 k5 [/ C% ^$ }& {
  8. #define USB_MC_CONFIG_DESC_SIZ 106
    ) Z9 f/ C' Y6 L* y2 v/ Y

  9. % I0 f- v( p+ Q3 V& `) ]6 g) Q

  10. ! O' H5 o# J) O* @9 E
  11. extern USBD_HandleTypeDef hUsbDeviceFS;4 S. M# x0 C0 T( W
  12. 4 f" a" |5 G& ]7 d

  13. 1 h& x% l' B' z
  14. extern uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);% M( R: R$ }5 w( f% M
  15. extern uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);/ W/ m9 \) m: q" ~  ^
  16. extern uint8_t  USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);8 ~, C0 f3 k; l& b- H
  17. extern uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);' |1 j& R+ L2 F1 K
  18. extern uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
    6 F" l# A, F& q6 _% E: z! `
  19. * d% d( F' e  U, [2 m" G! h

  20. , g8 A" Q6 |8 {) M) s
  21. extern uint8_t  USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
    / Z4 Q! Z$ D( ~* b4 c
  22. extern uint8_t  USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
    1 \" ]/ `- i: j6 K
  23. extern uint8_t  USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);+ W$ E! y# o' U7 {
  24. extern uint8_t  USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);! i% {* S/ J# [/ W3 O
  25. extern uint8_t  USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);! b( A7 o  _* L2 W% j6 s% E1 F
  26. extern uint8_t  USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev);/ i1 ]2 A" s, c
  27. 7 f2 c9 h( g7 X' a7 p' e7 N% W
  28. " f( G) _+ n  Z9 J  n+ Q# h3 ?
  29. static uint8_t  USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx);  q3 S) k6 i) F2 Q3 i% K7 S* |
  30. static uint8_t  USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx);
    3 b7 _0 ^0 r7 C8 o# X7 u
  31. static uint8_t  USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
    + V/ w' X( S1 O8 M
  32. static uint8_t  USBD_Composite_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);: k& h1 h: N5 }4 C1 ^  g, w+ N
  33. static uint8_t  USBD_Composite_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum);
    9 J% S' c, F+ A  }
  34. static uint8_t  *USBD_Composite_GetHSCfgDesc (uint16_t *length);6 `( h1 m; \. y/ W3 {) A
  35. static uint8_t  *USBD_Composite_GetFSCfgDesc (uint16_t *length);
    * J- A- ~4 G) x, l$ |$ _/ ^
  36. static uint8_t  *USBD_Composite_GetOtherSpeedCfgDesc (uint16_t *length);
    3 H/ G& {6 T' ]( ^) L6 @( N+ s) Z# {  U& O
  37. static uint8_t  *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);; E4 O2 p, ~4 `1 y
  38. static uint8_t USBD_Composite_RxReady (USBD_HandleTypeDef *pdev);7 h7 U! f( \( f/ D
  39. static void USBD_Composite_Switch_MSC(USBD_HandleTypeDef *pdev);
      O, z& q: L7 k  e! f
  40. static void USBD_Composite_Switch_CDC(USBD_HandleTypeDef *pdev);9 `4 k& v$ }: w" `9 o( ~

  41. 2 e9 K# u5 o- n  }4 O' H) G; L9 H

  42. / V- e' C0 r5 M; A9 D1 I+ v
  43. USBD_ClassTypeDef  USBD_Composite_CDC_MSC =
    ' B. c0 H* w$ U# s
  44. {
    ; Z, h& W+ @# b, o* O/ B, ]% x
  45.   USBD_Composite_Init,
    . S" n( w; q3 L8 a( a( t! Y8 l
  46.   USBD_Composite_DeInit,
    " [3 E: \* i7 R4 K  r% n
  47.   USBD_Composite_Setup,
    ! b( t$ D; x4 I7 W" U
  48.   NULL, /*EP0_TxSent*/
    % O  i4 m# G+ P3 j9 \+ C0 {4 f1 n
  49.   USBD_Composite_RxReady, /*EP0_RxReady*/
      b+ S* o: z1 X$ x
  50.   USBD_Composite_DataIn,
    6 G$ Z  h7 D) z, L! u6 t
  51.   USBD_Composite_DataOut,1 ?% [8 V1 z2 g
  52.   NULL, /*SOF */$ F; {9 ^! t5 S9 |3 u) Q+ G( W
  53.   NULL,; o+ s. W; l% O. R
  54.   NULL,  p$ L' @: G; `; Z5 f
  55.   USBD_Composite_GetHSCfgDesc,, ~1 c3 J0 |3 h) Q. ?
  56.   USBD_Composite_GetFSCfgDesc,( r" e: |: q) F& T7 k
  57.   USBD_Composite_GetOtherSpeedCfgDesc,1 O5 J, X. J" N! A5 a* M/ \! M
  58.   USBD_Composite_GetDeviceQualifierDescriptor,& v1 {: K" `7 b/ w3 g
  59. };2 f- W8 v: o) b2 W1 ^
  60. % A# l8 U$ `( C( s% f4 s

  61. - U+ T( u2 M2 t2 S2 v  Z
  62. /*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
      y' H, d$ V9 P6 h6 b, O/ A, O
  63. __ALIGN_BEGIN uint8_t USBD_Composite_CfgDesc[USB_MC_CONFIG_DESC_SIZ] __ALIGN_END =6 H, e2 w5 R5 r$ q3 ?) u
  64. {
    6 K: b/ y& y* N/ V" x
  65.   /*Configuration Descriptor*/
    0 E, @1 J3 R# e( \
  66.   0x09,   /* bLength: Configuration Descriptor size */
    5 t+ X/ Z2 p& k" B
  67.   USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration */
    0 G1 y, g" ?6 g; K6 k* w+ g
  68.   USB_MC_CONFIG_DESC_SIZ,           /* wTotalLength:no of returned bytes */+ g! i  r! ^7 l$ {* V: h
  69.   0x00,9 y3 L  n! \# T& k, f; X, Q2 c
  70.   0x03,   /* bNumInterfaces: 3 interface */ /* +++lakun:CDC用了两个接口,MSC用了一个接口,所以是3 */
    7 Y/ N" I) q; Z+ R1 L8 G
  71.   0x01,   /* bConfigurationValue: Configuration value */# H4 o' n2 m! x( O
  72.   0x00,   /* iConfiguration: Index of string descriptor describing the configuration */- k/ y4 M  A) L/ T
  73.   0xC0,   /* bmAttributes: self powered */5 G, v' K- A& O8 u" a" W* a5 Q
  74.   0x32,   /* MaxPower 0 mA */+ B, @: k) s5 Y0 ^3 \; X

  75. + H  F# F: S: w% t) M6 ]4 m# J; n' C/ {0 O
  76.   /*---------------------------------------------------------------------------*/
    " J* Q4 ^# ^5 N9 L3 q* y- I

  77. * S$ i+ j" g. m1 }
  78.   //* M2 z$ T) D. Q8 r
  79.   // +++lakun: IAD(Interface Association Descriptor),用于指示CDC1 [+ U+ k: r9 `$ i+ [7 \
  80.   //0 p* f$ J: e% l, m/ O
  81.   0X08,  // bLength: Interface Descriptor size,固定值
    ! s; Q* P+ C0 h# I+ |& q/ b+ u1 R
  82.   0X0B,  // bDescriptorType: IAD,固定值  d6 h, F# k* c8 P
  83.   0X00,  // bFirstInterface,第一个接口的起始序号,从0开始4 M6 k" k/ x8 ?- p  W
  84.   0X02,  // bInterfaceCount,本IAD下的接口数量
      k6 d7 }, R* T' Q( j- i& J  \% \& X
  85.   0X02,  // bFunctionClass: CDC,表明该IAD是一个CDC类型的设备/ \& \  Y; U% e" s; J7 K1 {
  86.   0X02,  // bFunctionSubClass:子类型,默认即可
    $ y9 D2 c: E& L8 Y
  87.   0X01,  // bFunctionProtocol:控制协议,默认即可! b3 A% W  k- ]1 v! w3 @* |% {6 D
  88.   0X00,  // iFunction/ y, d" d7 F! B+ F; K+ ?6 o
  89. 8 X( u( ]2 v4 f8 N4 C, t# U
  90.   /*Interface Descriptor */& k( g  b( Y4 Y2 v8 G% U8 U
  91.   0x09,   /* bLength: Interface Descriptor size */( s8 `7 k: c8 G( W+ l; e+ M( a
  92.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */! [( h6 A4 x4 Y! j! r+ U# T
  93.   /* Interface descriptor type */
    5 \6 |+ {9 O* Z9 W% v) ^
  94.   0x00,   /* bInterfaceNumber: Number of Interface */                   /* +++lakun:接口编号  */% w. b$ h! {7 g7 y1 M4 Y
  95.   0x00,   /* bAlternateSetting: Alternate setting */( Z1 o) y8 {8 S1 |, I
  96.   0x01,   /* bNumEndpoints: One endpoints used */0 @0 b, Y) s7 n3 T, T) d
  97.   0x02,   /* bInterfaceClass: Communication Interface Class */          /* +++lakun:表明这是一个通信接口 */
    1 c# A& g  }  {1 E
  98.   0x02,   /* bInterfaceSubClass: Abstract Control Model */: P" o3 ^9 u4 a) d: B1 |
  99.   0x01,   /* bInterfaceProtocol: Common AT commands */" ^$ t) t7 Y/ r: p8 V+ e
  100.   0x00,   /* iInterface: */1 O0 G7 W; c) `$ `- ^  Y
  101. 5 F. V6 f6 r0 E% i& n# {
  102.   /*Header Functional Descriptor*/
    # F9 o* ?& X/ D' b  @
  103.   0x05,   /* bLength: Endpoint Descriptor size */1 q* r) ]  z1 R5 p' O; N9 T8 T
  104.   0x24,   /* bDescriptorType: CS_INTERFACE */9 {2 y7 _$ o8 g4 D: g
  105.   0x00,   /* bDescriptorSubtype: Header Func Desc */0 z9 ^" u. B. ]7 n$ E
  106.   0x10,   /* bcdCDC: spec release number */8 M+ f/ S4 }: ~
  107.   0x01,) i# {, I' x8 C( N2 d

  108. ) ?- L2 \, `' c2 H* Z
  109.   /*Call Management Functional Descriptor*/
    . v0 @* P. Y. S, f
  110.   0x05,   /* bFunctionLength */
    2 C" R- ~) a0 P, J1 n
  111.   0x24,   /* bDescriptorType: CS_INTERFACE */2 F1 E) C" j' r( v  m; J7 I5 s
  112.   0x01,   /* bDescriptorSubtype: Call Management Func Desc */$ O  j' k# s0 h) g. u  m0 \, p
  113.   0x00,   /* bmCapabilities: D0+D1 */
    - T5 w+ S) u/ Z
  114.   0x01,   /* bDataInterface: 1 */6 X7 ~2 L) l" w% e0 _7 X' O, v2 c

  115.   U) Z* z( [* g: }; i
  116.   /*ACM Functional Descriptor*/
    . ^3 [4 E( X4 }' H" F
  117.   0x04,   /* bFunctionLength */, z0 d- Y# \. F# H! @" n
  118.   0x24,   /* bDescriptorType: CS_INTERFACE */
    9 J( Y' W4 n$ N8 g- V
  119.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    1 [& |5 I% k7 B! j# e
  120.   0x02,   /* bmCapabilities */
    ( x0 Y! t8 x4 M8 M$ c" `$ ~
  121. : c. z4 C1 \3 W9 r$ i3 s: ~' x/ z
  122.   /*Union Functional Descriptor*/
    5 ^& K  z6 f8 ?3 o& V+ Z1 g
  123.   0x05,   /* bFunctionLength */  d- }) X* ^( d* i* m) b- h5 B# ^
  124.   0x24,   /* bDescriptorType: CS_INTERFACE */
    & A9 u' A2 ^& u# @
  125.   0x06,   /* bDescriptorSubtype: Union func desc */
    8 w' e4 W) h: f# W; ~
  126.   0x00,   /* bMasterInterface: Communication class interface */           /* +++lakun:这里是用来指示CDC通信接口的编号的 */4 X  C* J2 _: M# Z5 P2 `; |
  127.   0x01,   /* bSlaveInterface0: Data Class Interface */                    /* +++lakun:这里是用来指示CDC数据接口的编号的 */1 ~- x6 f# P- ~7 k" ~
  128.   M2 a: L6 f: O8 d
  129.   /*Endpoint 2 Descriptor*/1 G/ K! e. }4 d$ N& j! S- l8 |
  130.   0x07,                           /* bLength: Endpoint Descriptor size */) _3 c( O& B& ^8 J
  131.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    2 D1 J* Y5 Y" }- O4 C
  132.   CDC_CMD_EP,                     /* bEndpointAddress */
    / F" i3 w! E6 F' a1 e# K
  133.   0x03,                           /* bmAttributes: Interrupt */. _: F# K9 v8 i
  134.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */- h- V- Q3 p. L! m  b3 t5 |& w
  135.   HIBYTE(CDC_CMD_PACKET_SIZE),3 b. k; _/ c$ H! L. F, n1 y
  136.   CDC_FS_BINTERVAL,                           /* bInterval: */, w2 f6 f4 V( N2 R9 ?% b8 n& J
  137.   /*---------------------------------------------------------------------------*/
    ! U  W" C* x" w8 [
  138. ! w! x. T. H: [+ e1 a0 S
  139.   /*Data class interface descriptor*/
    ; x' R0 ~! W) ]) v+ Z9 M& ~
  140.   0x09,   /* bLength: Endpoint Descriptor size */" @" O% R& J' `3 C, {, k! O
  141.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */, R+ f$ @, n6 M( z9 m) y
  142.   0x01,   /* bInterfaceNumber: Number of Interface */                     /* +++lakun:CDC数据接口的编号为1 */7 v# M+ ~; Q' @+ b* V7 Y2 q* @
  143.   0x00,   /* bAlternateSetting: Alternate setting */8 w% |& N8 R+ \4 H
  144.   0x02,   /* bNumEndpoints: Two endpoints used */
    # n" d$ B* ^5 b5 O; C1 K
  145.   0x0A,   /* bInterfaceClass: CDC */0 G" D/ X" m9 z( U
  146.   0x00,   /* bInterfaceSubClass: */. @" |* X- G# c# x+ M5 e$ z( O5 z
  147.   0x00,   /* bInterfaceProtocol: */# B, J9 K7 B* s; Z1 l) e6 l
  148.   0x00,   /* iInterface: */
    * N! i5 A& G6 ?+ z; s
  149. ) x' l6 T' b4 N+ q& c  ?, X1 F
  150.   /*Endpoint OUT Descriptor*/# S: k1 [9 w/ U: w/ n
  151.   0x07,   /* bLength: Endpoint Descriptor size */
    . |# M+ N0 E& c4 y7 o3 `; T
  152.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    1 x5 @2 A* L: m9 l. Q3 X3 \* B
  153.   CDC_OUT_EP,                        /* bEndpointAddress */
    ) j& b' b6 p: F
  154.   0x02,                              /* bmAttributes: Bulk */
    # S0 t  J, j, t/ Z( u
  155.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */( w# I" k' Z/ y2 S
  156.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    # w( X; R( c+ w# B. Z
  157.   0x00,                              /* bInterval: ignore for Bulk transfer */9 X$ s" {/ R( r8 D5 |: g% D

  158. 5 r) p9 m5 W" @2 ~! @
  159.   /*Endpoint IN Descriptor*/
    % J9 K# i5 y* o$ m+ T
  160.   0x07,   /* bLength: Endpoint Descriptor size */, n6 D0 ^. X0 f) k; D' Y" c, L
  161.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */& J5 x/ |; N% w4 m  [# R7 ]
  162.   CDC_IN_EP,                         /* bEndpointAddress */" T5 j4 x( {9 n9 `+ P* c
  163.   0x02,                              /* bmAttributes: Bulk */+ o5 |2 F: p( _, D3 m
  164.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */# R4 A- T' o( g6 a& J1 j1 m. C
  165.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),8 l. M/ ?# o* y) v* T0 L
  166.   0x00,                               /* bInterval: ignore for Bulk transfer */3 J  {' w0 j: [, Q' H% V4 S4 ?
  167. : V* A& T- ^' b& z# r9 [
  168.   //
    0 B; w9 G# R2 {: H/ i
  169.   // +++lakun: IAD(Interface Association Descriptor)
    ! R. g% n! K0 [  Y6 D% c
  170.   //9 l4 @/ i0 X# l8 w* j$ [8 B8 s
  171.   0X08,  // bLength: Interface Descriptor size,固定值
      K7 j* q2 J" q& k. a, e
  172.   0X0B,  // bDescriptorType: IAD,固定值
    % _% H+ L- w: O$ P
  173.   0X02,  // bFirstInterface,接口的起始序号(第0、1编号的接口用于CDC1,所以从2开始)
    5 ?1 i$ f( E0 i5 o0 C
  174.   0X01,  // bInterfaceCount,本IAD下的接口数量) W2 I3 N/ u0 y1 d% ]2 T
  175.   0X08,  // bFunctionClass: MSC,表明该IAD是一个MSC类型的设备
    & U$ p3 Z4 o8 U2 {2 @2 G7 Y: x  C9 U
  176.   0X06,  // bFunctionSubClass:子类型,默认即可
    . X. a4 n- E' y- y" m) [- }" @
  177.   0X50,  // bFunctionProtocol:控制协议,默认即可
    * B+ C0 N2 t% v2 W" n
  178.   0X05,  // iFunction
    ; X7 H; F3 @+ p' Q' O- l

  179.   l/ W6 G. D, F3 I: N; @/ F
  180.   /********************  Mass Storage interface ********************/
    7 g+ D' N. k- z
  181.   0x09,   /* bLength: Interface Descriptor size */
    / v+ z- @( ~! J! A4 P
  182.   0x04,   /* bDescriptorType: */2 k' L8 R6 j$ F7 G) B/ X( M
  183.   0x02,   /* bInterfaceNumber: Number of Interface */  /* +++lakun:第0和1编号的用给了CDC,所以MSC接口的编号从2开始 */) P  U. q6 Z- r' t! d9 U
  184.   0x00,   /* bAlternateSetting: Alternate setting */
    " d: W# i* \# V2 `
  185.   0x02,   /* bNumEndpoints*/$ R" C5 n) V/ _% L
  186.   0x08,   /* bInterfaceClass: MSC Class */3 W2 ?! k- J* c2 y8 c( Y
  187.   0x06,   /* bInterfaceSubClass : SCSI transparent*/
    . I) v, r% C% Z% d# N5 j
  188.   0x50,   /* nInterfaceProtocol */0 {! P* Y  d) e
  189.   0x05,          /* iInterface: */' l0 I" Y9 E! ?
  190.   /********************  Mass Storage Endpoints ********************/
    . Y- {9 L/ o% [# ^+ z$ k1 G
  191.   0x07,   /*Endpoint descriptor length = 7*/. B: O% G; `! o* J% W
  192.   0x05,   /*Endpoint descriptor type */
    , i% C. `( |7 P+ r: w' R+ Q3 q
  193.   MSC_EPIN_ADDR,   /*Endpoint address (IN, address 1) */
    ! M3 _: `! q4 Y2 O4 w: B
  194.   0x02,   /*Bulk endpoint type */7 v5 M. F4 d7 Z, m8 m+ E
  195.   LOBYTE(MSC_MAX_FS_PACKET),. |# m& s7 H  r% w; t7 P( i
  196.   HIBYTE(MSC_MAX_FS_PACKET),0 g$ m. `$ @8 R1 ~
  197.   0x00,   /*Polling interval in milliseconds */
    6 y$ o/ a" K3 M: ]) x& h% ^) x" x

  198. 3 {; y5 f" O" W2 ~4 T' f! x
  199.   0x07,   /*Endpoint descriptor length = 7 */
    1 J: b+ F) X5 [0 o* J
  200.   0x05,   /*Endpoint descriptor type */% H) {/ G1 t9 e4 H$ k
  201.   MSC_EPOUT_ADDR,   /*Endpoint address (OUT, address 1) */
    6 X% R' S' G! b0 B4 U
  202.   0x02,   /*Bulk endpoint type */
    ! Y1 j3 @0 r7 R1 E! N
  203.   LOBYTE(MSC_MAX_FS_PACKET),
    " T7 `2 @* J) B* O+ a; j6 v" c
  204.   HIBYTE(MSC_MAX_FS_PACKET),
    % o; v: I% H& o$ |8 N3 X. z
  205.   0x00     /*Polling interval in milliseconds*/
    2 k/ @% }# u/ R: F* X
  206. } ;) i4 }8 Z; s- o* |

  207. % ?7 ^8 ^1 e* {

  208. 2 _9 Q( k6 F/ o4 P& l$ `
  209. /* USB Standard Device Descriptor */
    5 i" l! m/ A  M" e  V/ S
  210. uint8_t USBD_Composite_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] =
    ; V- S  ^  f% n3 q
  211. {* @! [  ]0 g% L$ k
  212.   USB_LEN_DEV_QUALIFIER_DESC,
    : l2 ~% m7 C, o+ C" c: e% N
  213.   USB_DESC_TYPE_DEVICE_QUALIFIER,
    # [% |) e- V' J7 F
  214.   0x00,4 n- C# |9 W5 p0 Y& l
  215.   0x02,5 C% v; z/ w0 D+ i& Y, r/ r
  216.   0x00,
    5 X8 [' N4 _1 A2 k5 g
  217.   0x00,, c0 u6 [' D, h. }( a) n- o
  218.   0x00,
    2 Z4 j" ?/ H  ?. S! h' \7 X1 _
  219.   0X40,
    2 T2 Z) a# \5 f
  220.   0x01,
    : A/ b! u' r3 k8 C
  221.   0x00,3 f5 Q9 C+ }, g8 L
  222. };" b% b# Y% G1 P8 n% b- K- f8 v) Z
  223. . H: a2 e5 H  F! l$ w
  224. , y% S$ }% }6 Y
  225. // 这个函数是修改的USBD_MSC_Init
    / e  L" U- u- |$ @7 u: Q" N7 \
  226. static void USBD_Composite_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)1 A' I* n9 M. L
  227. {( `" V$ K1 V* S  w  K
  228.         USBD_Composite_Switch_MSC(pdev);
    6 Q6 L1 I8 j9 J; T! w3 S3 @
  229. ) U) y' p3 t& B  U
  230.         /* Open EP OUT */
      [5 t, }. L& W- K7 m1 g6 v& e
  231.         USBD_LL_OpenEP(pdev, MSC_EPOUT_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
    6 B! f! s  X' }: [7 p. r" z$ r8 N
  232.         pdev->ep_out[MSC_EPOUT_ADDR & 0xFU].is_used = 1U;/ T8 b, f$ G) c) k
  233. / a2 l; g5 }$ p6 |
  234.         /* Open EP IN */3 S, R1 ^# W7 B1 I2 u4 {
  235.         USBD_LL_OpenEP(pdev, MSC_EPIN_ADDR, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
    8 h6 N* f# `" k( w2 {/ @# D
  236.         pdev->ep_in[MSC_EPIN_ADDR & 0xFU].is_used = 1U;
    $ w' {7 `7 w% n9 a
  237. 4 d2 r3 o. |. r6 Q# _; X+ j
  238.         /* Init the BOT  layer */, A. {" h7 x$ x$ u4 r1 o# H/ N
  239.         MSC_BOT_Init(pdev);
    * b& w; A, Z# ]  u' `
  240. }
    , {" V3 g5 s3 Y3 s9 p: `
  241. ( w/ X% X0 _# W$ Z
  242. // 这个函数是修改的USBD_CDC_Init
    : T# m+ _0 O6 h& ~0 [* V: Q
  243. static void USBD_Composite_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
    : e7 L5 ?% x# q4 _8 u: o. h% s
  244. {  i7 W3 ]! u: a  G6 G
  245.         USBD_CDC_HandleTypeDef   *hcdc = NULL;
    ) d' z- m% b2 R
  246. . |  w6 z0 Y1 j* ?6 ?. n/ B' V. M% v  A
  247.         USBD_Composite_Switch_CDC(pdev);& U- F9 y) h" u5 c5 s
  248. & H" @! y) {7 b0 U& _% G- h
  249.         /* Open EP IN */
    * \. V0 C' @! W
  250.         USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK, CDC_DATA_FS_IN_PACKET_SIZE);
    # R# _* g' d9 U! `+ `0 w/ k
  251.         pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;7 g; N5 o# ]7 v7 j) B& K

  252. " i2 R+ q" o4 |) ]1 B' O
  253.         /* Open EP OUT */
    " A( @* f) W+ O/ `$ W0 I
  254.         USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,CDC_DATA_FS_OUT_PACKET_SIZE);
    9 u0 m" Q8 p5 f: F
  255.         pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
    5 @6 c: }; g8 E" r

  256. + @5 c0 f% E5 ]# P6 ~
  257.         /* Open Command IN EP */
    ! P8 f/ [( Z& {7 S; g$ F6 r
  258.         USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);' ^3 I6 l; s& H* r# ]
  259.         pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;, p+ h0 N% B% Y8 M; s

  260. 6 f1 L  M- Y3 d* W
  261.         hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
    ! ^7 p; T. e  @$ {

  262. % _4 z$ H, }7 e' Q
  263.         /* Init  physical Interface components */+ u. f$ y9 @+ F
  264.         ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();4 \: S* L" j. a( p/ x- {4 L& e
  265. ! F. i& K7 U  W; X- e! _% C
  266.         /* Init Xfer states */3 I6 U  R2 f( g4 K) i" Z0 {& P
  267.         hcdc->TxState = 0U;
    9 O& h1 ^2 i9 n. W
  268.         hcdc->RxState = 0U;
    * w" v6 L/ j# ~- B+ n; V; Q1 W
  269. ! I0 G3 H$ n( w: _
  270.         /* Prepare Out endpoint to receive next packet */
    ' R  M4 w/ }- {, ?3 u& Z
  271.         USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer, CDC_DATA_FS_OUT_PACKET_SIZE);
    0 b* a/ Q# ~! y3 q* }8 g) n0 K
  272. }
    # r0 Y3 A" _# m, U9 _/ ~
  273. 9 ^9 X8 i9 S4 ^- A0 Q
  274. uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
    0 C+ b( `1 v+ S: Y5 v
  275. {9 T* J' E6 i, S' i
  276.         USBD_Composite_MSC_Init(pdev, cfgidx);  // 初始化MSC+ {: C) |, m. b+ ?/ b
  277.         USBD_Composite_CDC_Init(pdev, cfgidx);  // 初始化CDC
    7 q5 ^; |$ s, d4 t& U) T2 L& H
  278.         return USBD_OK;
    9 P( A0 V/ n( S1 b. ~7 f
  279. }
    6 z1 N) z' x3 y* t8 |  r

  280. 1 c2 ^* S9 |4 B4 j0 `9 v6 r
  281. uint8_t  USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
    $ E! v) V; t7 ?- m* \
  282. {* E& y8 q3 V) P0 X) L, \& _
  283.         return USBD_OK;1 a& Z2 S$ K: M6 o! U2 C5 \% v+ @
  284. }
    ; E0 x: q* X0 |
  285. ) X, O+ p1 F4 [* V( G$ o
  286. uint8_t  USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)( |6 L! G$ [' A8 w0 _( G
  287. {) J: j6 \  e2 u8 n0 V
  288.         switch(req->wIndex)  // wIndex是接口编号,在配置描述符里面我们第一个IAD是CDC使用的是编号0和1两个接口,第二个IAD是MSC使用的是编号2的接口
    ) H# n5 v8 z! }1 t$ }
  289.         {* q3 C6 [. z8 T; X% G; ?

  290. 0 b4 s9 \) \  K0 K- n( `' s8 |* U7 f! V
  291.         //
    6 f# i7 S4 b; A: N- N
  292.         // 第一个IAD
    / T6 G! j$ k" R  b% r5 [
  293.         //- E2 S3 o* ~$ I
  294.         case 0:  // CDC的命令接口编号为0: o0 B- |- I) S! k8 L1 M) C
  295.         case 1:  // CDC的数据接口编号为1: P# E- m" b( S  y$ f" e' m
  296.                 USBD_Composite_Switch_CDC(pdev);
    7 i4 [5 k8 V7 H* l6 w: H. }! j
  297.                 USBD_CDC_Setup(pdev, req);
    1 ^- F# \- L$ J! i4 q1 s
  298.                 break;+ L4 n, ?5 }% b# B+ F
  299. 0 b; A2 ]  b; W% B* z; y' b: l
  300.         //* Z0 V: ?3 Y4 _2 W  N( a
  301.         // 第二个IAD
    ; [4 s5 P5 i) s. D( V
  302.         //+ y; [, Z7 l$ f8 J7 n
  303.         case 2:  // MSC只有一个接口,编号为20 r) \: f1 q. [
  304.                 USBD_Composite_Switch_MSC(pdev);
    ' f8 b1 O7 I' ~3 N  Y8 U6 Z
  305.                 USBD_MSC_Setup(pdev, req);
    7 ~. t% e) E; X3 x8 l9 P1 g
  306.                 break;
    * @7 L! y# v1 b9 X1 Z( @3 G& @
  307. + S  }3 M. b1 A0 }9 t
  308.         //
    $ i' s8 ]0 s1 v# M/ p
  309.         // 第三个IAD(如果有,在这里初始化)" ]  |9 F/ Z" M4 `$ Z( h
  310.         //% z* h# v3 J( r- |( X
  311.         case 3:
    - D: {/ P" A4 F& N. N" N2 F( t( Z
  312.                 break;( T2 g' ]9 o3 p- c/ f0 h$ v1 t
  313.         default:break;
    / t: M0 A0 s& M+ j" u+ v: b0 H8 d- A, x
  314.         }1 ~( r& ], ^$ H( j6 @- v
  315.         return USBD_OK;
    . N/ e, u- R% y5 c7 x* q
  316. }& I0 E% u9 \2 ?  U% P7 D
  317. % y, J: [5 N" c% i4 y. G  ~
  318. uint8_t  USBD_Composite_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)( L0 p6 D6 t3 K! j
  319. {: ?- v. h8 C- N4 R5 ^$ ^- Q
  320.         switch(epnum | 0X80)
    & q- S7 F$ Y$ ]+ h6 a
  321.         {
    + Y) w: I; j4 h7 |5 ?- W
  322.         case MSC_EPIN_ADDR:( L7 A6 }$ L4 h2 Q" U& l/ W
  323.             USBD_Composite_Switch_MSC(pdev);. k* Y* x& X0 X, X
  324.             USBD_MSC_DataIn(pdev, epnum);1 C3 R# s8 \$ H, b7 \( ~; T
  325.                 break;8 R8 ^, w' W( i7 D
  326.         case CDC_IN_EP:  p3 \# F$ f7 S
  327.             USBD_Composite_Switch_CDC(pdev);; ^. [1 z5 {: z% m% n4 q3 `, s
  328.             USBD_CDC_DataIn(pdev, epnum);
    + s. z% ?8 N4 z6 f4 u7 c3 q0 I
  329.                 break;
    # {2 F+ u  J9 ?  d" u2 e
  330.         default:break;% b* \( j4 p& V) k6 a$ J
  331.         }0 y$ w: S1 S- p$ o

  332. $ g  W7 M% ?% q3 _0 j( K$ x. R
  333.         return USBD_OK;5 X# E3 ~( `! m2 P( [
  334. }; I" r7 a5 h+ Z9 S! P8 d
  335. ! D) D+ |6 t* q2 x; O5 s0 Y  _/ t" Z% D
  336. uint8_t  USBD_Composite_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
    ; F3 v3 }4 w$ |) H5 l) o. m% \- Z
  337. {
    $ ?4 {% D  i1 T# ]: ]1 S" M+ P
  338.         switch(epnum)1 F  V; ^% s, A6 `
  339.         {
    % U! {+ X/ M- X0 Y" U0 B
  340.         case MSC_EPOUT_ADDR:
      O3 J/ W$ ]! i
  341.                 USBD_Composite_Switch_MSC(pdev);( W% m4 \/ }& {8 U' C
  342.                 USBD_MSC_DataOut(pdev, epnum);! e, ^( v& a2 M; k. O: U
  343.                 break;
    ( N5 P& H/ V  I/ M9 Z9 V
  344.         case CDC_OUT_EP:
    ) |7 m; \/ ?5 [8 H7 Z% H
  345.                 USBD_Composite_Switch_CDC(pdev);
    0 n0 J6 v, c, r1 s) T. h, u
  346.                 USBD_CDC_DataOut(pdev, epnum);0 {0 T  p* s) N$ M% U4 _
  347.                 break;4 [0 N& x9 {3 V8 B
  348.         default:break;( |7 r% R3 B" V4 x# E: G# o+ M
  349.         }* ?) Z  t$ O. ]/ C1 g' W* v
  350.         return USBD_OK;
    ' }1 @- c/ I7 r2 c. d" w# n
  351. }
    # D) d. ]  O9 {; R; m3 F

  352. + w) A! k, w3 u. F" I' W. f0 c% p' J* ?
  353. uint8_t  *USBD_Composite_GetHSCfgDesc (uint16_t *length), p8 Z* t0 d! [& {( Q  I" B
  354. {/ F, Y% N3 m, ]+ x4 ^3 F% J
  355.   *length = sizeof (USBD_Composite_CfgDesc);4 \# Q. P9 D* B& G* @; B
  356.   return USBD_Composite_CfgDesc;
    ) z& f5 v  ~9 `) ^- W
  357. }  Q1 [/ M3 i/ `5 F+ Y
  358. ( ~- A+ M9 l" y) a) N
  359. uint8_t  *USBD_Composite_GetFSCfgDesc (uint16_t *length)
    # W  ?. G4 X: w% n
  360. {; R' @5 u, G" y/ ]: [! D
  361.   *length = sizeof (USBD_Composite_CfgDesc);
    8 b% S# P! f) B, w) @9 F- m
  362.   return USBD_Composite_CfgDesc;
    1 T2 v# i4 L/ J! m5 Q. k
  363. }
    , F$ K5 s$ y" h0 i2 o6 \, W- Y
  364. 1 Y: Z3 x, ^" \4 f$ v4 F
  365. uint8_t  *USBD_Composite_GetOtherSpeedCfgDesc (uint16_t *length)
      {. p8 E9 V- C( |2 I( r
  366. {4 i, ]# S; r) A9 Q
  367.   *length = sizeof (USBD_Composite_CfgDesc);  U1 D$ T/ q* Z
  368.   return USBD_Composite_CfgDesc;
    - u$ F1 ~$ ]8 D* C/ L+ Q
  369. }
    * }, V2 D7 s8 N6 V; Z* \$ F5 m; V

  370. ; j( F$ i1 v% W6 \! E, z
  371. uint8_t  *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length)
      O4 x- o# M: A1 B
  372. {
    . [* D, n" D* K. A! h$ q* n
  373.   *length = sizeof (USBD_Composite_DeviceQualifierDesc);( T1 B+ w1 P/ N& d/ o/ P- Q
  374.   return USBD_Composite_DeviceQualifierDesc;
    ) u" Y2 K5 m" F7 ]2 Z! N( m
  375. }6 V2 T" X0 F. d& ]2 F' l2 d
  376. ) M2 T3 h4 p1 S
  377. static uint8_t  USBD_Composite_RxReady (USBD_HandleTypeDef *pdev)) o0 j$ B( F1 D, d/ X6 a
  378. {
    3 i6 b5 y' h. D! `3 T
  379.         uint8_t ret = 0;
    ' B% |& S! l) o4 V& P
  380.         switch(pdev->request.wIndex)  // wIndex是接口编号,这里我们通过接口编号确定CDC还是其他设备的EP0接收* x/ @; a6 |# B$ D. X6 S9 Y
  381.         {9 R) M2 A8 v* f1 [5 p5 d5 F
  382.                 case 0:  // CDC的命令接口编号是0! ^/ J# b7 b, F2 ?
  383.                 case 1:  // CDC的数据接口编号是1( S6 Y. j7 j) I0 T/ k
  384.                         USBD_Composite_Switch_CDC(pdev);
    1 r1 k0 l/ B. |+ K, }
  385.                         ret = USBD_CDC_EP0_RxReady(pdev);
    * c  `$ p- E0 s
  386.                         break;/ k! F/ A; ^! k7 H
  387.                 // 如果有其他设备还用到了EP0接收,在这里加入
    & Q$ G, t3 |8 y) f( q7 o/ f: {, w9 R
  388.                 case 2:
    : g2 O. [3 N( e# y8 D! X& d
  389.                         break;) t. j, m) ~$ k
  390.                 default:break;# o6 d8 i" H7 d
  391.         }
    7 [4 q( v3 D5 v  `4 L
  392.     return ret;
    0 m& K: D* U- z: l& {, ~/ Z
  393. }
    2 R+ A/ D+ r9 C& ^* q9 P
  394. 0 x9 o. ~( h" R" Q
  395. static void USBD_Composite_Switch_MSC(USBD_HandleTypeDef *pdev)
    ! G" a, v8 {6 H: N* ^
  396. {- n, L& t$ I; B' ]2 b# B3 p
  397.         static USBD_MSC_BOT_HandleTypeDef USBD_MSC_Handle;
    4 ~" u/ V4 \& s
  398.         USBD_MSC_RegisterStorage(pdev, &USBD_Storage_Interface_fops_FS);
    * x! g: D, @9 ~, y2 M
  399.         pdev->pClassData = (void *)&USBD_MSC_Handle;
    . g+ u1 m, m- m4 _* I
  400. }5 D" U% [, o$ X" N

  401. - K7 O/ A) ^8 D! i5 U& i
  402. static void USBD_Composite_Switch_CDC(USBD_HandleTypeDef *pdev)( H: {5 l1 _  v4 M) J# w2 B/ {# W6 z
  403. {
    ) R, X3 D$ W- i
  404.         static USBD_CDC_HandleTypeDef USBD_CDC_Handle;! M/ {9 h- y* n# I
  405.         USBD_CDC_RegisterInterface(pdev, &USBD_Interface_fops_FS);
    & g' Q) @: t4 j0 g7 Y: Q
  406.         pdev->pClassData = (void *)&USBD_CDC_Handle;
    ' P2 O# n1 A' A8 s: c
  407. }
    + F! H: X) z+ c
复制代码

$ n" H, H8 h; E0 P/ v其中有关设备描述符的修改,我都用+++lakun进行了标注,并写上注释,方便查看。5 _8 i* W. k* \! }! w2 }8 A
! ?! p, T( U0 q4 A% m+ g) y$ L
第五步:MX_DEVICE_USB_Init修改
  ^2 `  U! n7 j  ?上面我们已经完成了统一接口的编写,现在就可以修改MX_DEVICE_USB_Init函数了,屏蔽掉接口注册函数USBD_CDC_RegisterInterface,然后将类注册换成我们自己的组合设备,如下图:' g# z6 f% d* Z( e

) _# n9 d2 y  L; E' h, Q8 e ~V(N24[X4FFR~H~TYROQ{5N.png . }( h" }* r0 r1 ]$ t9 R% n

) K6 {( F2 {0 ^9 u: Z' [& z到这里就已经改完了,运行程序之后设备管理器会出现:一个组合设备、一个虚拟的串口、一个USB大容量存储设备,如下图:
" |7 y5 f* J. A) Y* i3 Y/ n" V) k& o# J& X. n
20210425090801727.png
, D% I& v% q, D" q+ h
' v* f6 ~2 W1 e3 \. h+ m这样就是成功了!& i. N/ k$ w) g$ a$ y# }4 l

$ J8 l8 J- u' @/ s6 O) n!!如果修改过后发现设备管理器的MSC或者CDC显示感叹号,那么在回头检查PMA的配置以及组合设备描述符!!( @7 Q. u1 u; O" p" a

9 L, c& R2 u% G! X( d2 u5 {, |遇到的问题, [* N2 A. \0 c- L
我修改完毕之后,将板子接入电脑,虚拟出来的串口没问题,但是就是死活认不出U盘,后来找到问题的原因是因为我先使用的CDC串口这个单独的工程,我的win10已经默认枚举成了CDC,所以认不出U盘。
) y7 |* g* D/ N  S; a& r+ J) [
5 w  N7 _2 `5 x) p解决办法:
* Y4 Q: I  ]  @  u- b6 ?; d# l- h1.卸载识别出来的串口,重新拔插
' ^% X  J$ v( B: e, ?+ _9 Q5 \2.在程序里修改一下PID$ p) B5 X0 E% j( ]9 @' `* V: O4 x) Y0 ]
& r1 U4 \! W1 ^1 O
, o) E' U7 {5 }8 T9 u! a
S30Z~TQ%1__%MHK`IJ2XN6N.png
( a: i; \# _/ n. B6 b4 O
6 ?- H: d) S& `: ^, @( k我是用的第二种办法解决的!
; Y: ^8 o' i+ m1 i1 U7 U# E4 [1 J- a; W4 ]! T# M% @- m" E- Y

; L4 [/ r/ S& b% [3 S1 r3 d" t9 Y
收藏 评论2 发布时间:2022-4-9 23:20

举报

2个回答
小白小灰 回答时间:2024-12-14 13:36:11

不需要composite.h吗?编译出错,有几个没定义的。能给个源代码吗?不胜感谢

小白小灰 回答时间:2024-12-18 09:33:46

小白小灰 发表于 2024-12-14 13:36
不需要composite.h吗?编译出错,有几个没定义的。能给个源代码吗?不胜感谢
...

是拼写错误导致的,程序可以运行。谢谢

所属标签

相似分享

官网相关资源

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