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

STM32 USB如何配置多个CDC设备---5个CDC设备

[复制链接]
STMCU小助手 发布时间:2023-1-3 19:55
1. 背景
  • 由于项需求,在STM32F072中需实现5个CDC设备,折腾了很久分享出来,希望能帮助别人少踩一些坑.USB2.0全速,该款单片机支持8个输出和8个输入端点
  • , t# v" v% q: U! J5 W
2.1 它是什么?需要使用到什么?
  • 它是USB设备类型的一种,如U盘插入电脑时,电脑会知道其是U盘,是一个存储设备,那么它就属于USB MCU存储设备。USB协议中对设备进行了分类.它在stm32上叫虚拟串口设备,当将其链接电脑后,可以把它当成串口使用,如使用windows的串口工具打开它,设置波特率等等,这是我的理解。5 O0 e7 g" i  s' j

: r/ T2 }7 m, p, ^
  • 它需要两个接口,三个端点
    7 a# }% o# k5 I. y7 \+ M' X

" n# Y: ^% C, I! t. [0 E# _
  • InterFace 0:第一个接口,其包括一个端点,和Functional_Destriptcrs,该端点为控制接口(输入型端点(IN)),Functional_Destriptcrs则是一些描述符。先不管这个
  • InterFace 1:第二接口,其包括两个端点,endpoint In 和endpoint out端点,IN为stm32数据输出端点,OUT为stm32数据输入端点,随便提下,在STM32 HAL库中,USB的IN,OUT是相对于主机而言的,如:上诉的IN是指主机的输入,主机的输入(IN),对于设备来说就是OUT,数据的输出端点,IN OUT都是相对于主机而言
    / @2 z! b* M& [# p$ G+ L% R3 s
  • 由此可见,正常情况下,一个CDC需要三个端点,其中两个IN端点,一个OUT端点
    6 ]" ?+ \) }' Y$ N5 L( m

    9 \) z3 Q- d5 M7 D
3.配置过程3.1 配置流程
  • 在STM32CubeIDE的帮助下,生成一个CDC的代码,这里没什么坑,点几下就成功了,注意的是可能需要将Heap设置大一点
  • 修改设备描述符
  • 分配端点和修改配置描述符
  • 分配PMA端点缓存地址
  • 修改HAL库关于CDC部分函数接口的参数,以适配多CDC设备的情况! K6 z1 R: D5 V  m+ ~$ s$ A& G

1 V! @+ u9 K$ ~1 G  h8 \$ W

. E" u* B! f, ~3 v6 t! s5 R" N" G3.2 使用STM32CubeIDE生成一个CDC程序的代码
  • 根据下面的文件操作即可,文件会介绍USBCDC的知识,在PDF的最后会说怎么使用cubeIDE配置,很简单没什么坑(注意的是可能需要将Heap设置大一点)
    + x8 q4 _  R+ s( E* ^9 k. R7 ]
4 c' O- Y3 [  k7 n2 y# I

. v( n/ h. A$ k" R' ~3.3 分配端点和修改配置描述符
  • 此时问题来了,CDC要求3个端点,其中2个输入1个输出,而stm32F072只支持8个输入端点,8个输出端点,2x5>8,正常情况下是不够的,这里就需要将IN端口中的控制端口省略,也就是第一幅图中的Interface 0中的endpoint IN端点,不分配有效端点给它,在本款单片机中IN端点的有效范围(0x80-0x87),OUT(0x00-0x08)
    , H# Y& Q0 F/ p5 T/ d" V

2 d) Q& g, I; e- a
  u/ q" j0 f1 s2 @8 E  l# M
  1. #define CDC_IN_EP                                   0x81U  /* CDC*/
    ( F* O# D9 \  u: V
  2. #define CDC_OUT_EP                                  0x01U  1 j8 |! H6 P% s9 o! w7 O' l
  3. #define CDC_CMD_EP                                  0x88U  //无效端点
    ! _% D& R7 e! H% U' l. R5 w, G

  4. ! b, I2 b" ]1 B: m* u; V) r
  5. #define CDC_IN_EP1                                   0x82U   /* CDC1*/
    / w" m0 u, U/ Z' ^0 }" Q: H
  6. #define CDC_OUT_EP1                                  0x02U  ) H+ ]; b6 Y5 z8 y' [
  7. #define CDC_CMD_EP1                                  0x89U  //无效端点& k; K2 n. o& }' p

  8. - D+ a3 C* u6 B$ b  U  u% Y; R
  9. #define CDC_IN_EP2                                   0x83U   /* CDC2*/% N- b3 h& o5 F5 l( Y. @
  10. #define CDC_OUT_EP2                                  0x03U  
    ' N. B" q! X- ^: E
  11. #define CDC_CMD_EP2                                  0x8AU  //无效端点! Q, @1 f& C' L# ?

  12. 3 E# d! p* k/ ^; y
  13. #define CDC_IN_EP3                                   0x84U   /* CDC3*/
    / F! h( V- W' [/ H2 K' ?+ S
  14. #define CDC_OUT_EP3                                  0x04U  
    2 |/ a% u7 {' f
  15. #define CDC_CMD_EP3                                  0x8CU  //无效端点3 Z4 Z) g: d3 i7 e) c
  16. / A8 |9 G( N; p0 R
  17. #define CDC_IN_EP4                                   0x85U   /* CDC4*/( C8 Z. \" f1 i; i& F- T$ s: e  [
  18. #define CDC_OUT_EP4                                  0x05U
    ! d2 D; e( e% W% R$ N. l
  19. #define CDC_CMD_EP4                                  0x8BU  //无效端点
复制代码

& Q8 f! s; Z. L/ }! }4 p0 }2 z
& B# C# P: H: r" F# o
  • 修改配置描述符号,这里面的内容就很多了,里面涉及到USB方方面面的属性和参数,其中USB_CDC_CONFIG_DESC_SIZ是该结构体的大小,记得修改,或者直接改为最大255。
    : Q( h- j! I( W1 _7 J; ]4 S
  • 配置描述符的结构如下:
    ( W3 k& `5 J7 O. x  H

    3 q4 r) H$ q! b% C$ p8 @: Y6 }
  1. 配置描述符
    ) S$ R" w0 k6 W2 L7 x6 h! R0 z3 g
  2. {
    5 Y" w6 S, ?) J& {8 O9 v- ]2 |
  3.     配置描述符总概括(相当于预览:9字节)* X* I! {6 P" h
  4.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC
    - P. p* F6 b& F; c. n: d2 d. h
  5.     {
    " G3 F! j8 X' u* |, u
  6.         接口描述符1) M; {5 h5 o6 m$ a
  7.         {
    # S- ?- H8 Y9 j4 M/ K+ L
  8.             其他描述符(ACM等), H3 \( _1 n: T
  9.             端点描述符(控制端点)
    . {/ M6 z$ t& }  c
  10.         }: _! J7 K) x! O8 l- C) x' Z' |
  11.         接口描述符21 K( k4 w" h: ]( W" [5 U' k
  12.         {
    ' f. k! c4 C) [0 G
  13.             端点描述符(IN)2 D; [9 Q" Z+ f7 E5 m1 k
  14.             端点描述符(OUT)
    5 I4 u; e- G3 X  P- s, K0 Q% q1 w
  15.         }
    + G- |0 Q: ^$ q* ]! S' |
  16.     }  D  @  i( ~. M
  17. 9 ^2 L( `1 Q6 X8 R& H& w4 a) i( [
  18.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC1
    - \4 B7 x6 g3 t- N. t; F4 O0 A
  19.     {
    + R: }9 J: ^1 T1 K+ u9 @* f  M
  20.         接口描述符1& _0 H3 D* x1 _
  21.         {3 M0 [1 L* a8 a; c
  22.             其他描述符(ACM等)  }; l" U+ a1 a0 z7 c
  23.             端点描述符(控制端点); X* F3 H. g3 i4 |1 |4 H
  24.         }9 [- B# P. |+ B& Z! c8 s
  25.         接口描述符2! e  |2 }6 M  }* h+ Y3 w6 a! l; i
  26.         {
    ) q! h- h7 i/ N4 h9 Z
  27.             端点描述符(IN)
    6 [. d, _9 U$ s9 a8 m, ]; ?8 y0 H) t
  28.             端点描述符(OUT)( ?3 |9 B! D2 V1 }" ~( u" T
  29.         }
    9 I$ }: z; q" y4 O: j
  30.     }5 N' N8 e. \: T# T( Y, V

  31. ' l9 T  ~8 X" b) x- r- f/ U; d. K/ f
  32.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC2
    - a! ?# M1 V5 i# M
  33.     {( e9 I' O; X3 W+ p
  34.         接口描述符1! U! S) q4 ~- c7 T/ i: h
  35.         {
    # W: h. z4 X$ x+ H0 e* o5 u
  36.             其他描述符(ACM等)9 F, U6 o8 u& }& M- X4 l8 T( r9 z  w" e
  37.             端点描述符(控制端点)
    ' j% s. ?- U8 T* M) V- e
  38.         }5 O% _' @, N: A' S8 Q
  39.         接口描述符2
    1 D5 W2 H7 Q" I( t9 k/ [, R- T; I
  40.         {
    7 u' e7 Q1 c' Q$ ^+ I3 ]# W5 ~# a
  41.             端点描述符(IN)  }* v# g: O. z% ^4 {. A
  42.             端点描述符(OUT)
    ! K: y" m3 L8 V: `+ Y# o0 A' s
  43.         }
    ( K, E- H4 x+ c2 r0 c" m
  44.     }
    ! h0 X, |+ l) O. j  P- A8 s

  45. + i# L9 R  A% C" I, O
  46.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC3
    1 s# L8 ], d; @% S8 W
  47.     {
    * {3 `) e6 {1 s4 S
  48.         接口描述符1
    * F1 [" ~+ S) x, q4 l/ q' \
  49.         {# p) X+ [! G/ j
  50.             其他描述符(ACM等)
    5 \* ^, B/ W* g, n4 J
  51.             端点描述符(控制端点)
    ( D' D: M$ b; n! E. z
  52.         }. N3 `4 [, }! }6 r7 w' Y
  53.         接口描述符24 j# d0 ^0 U0 o& ?
  54.         {! v& i  `6 @0 _2 f  R
  55.             端点描述符(IN)
    3 J4 D0 _6 e; ?! N. w: k* a
  56.             端点描述符(OUT): t# P" T5 T" ]
  57.         }
    2 t2 G. c+ j% M/ N9 W0 }
  58.     }
    1 _9 T5 @, d' B, H  ?3 k
  59. / g  X6 q2 m/ O3 f0 [7 Z* {
  60.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC42 ~. h; d; ^0 b" x+ \9 l0 l$ e
  61.     {
    4 C5 P- r9 `# N$ i7 r
  62.         接口描述符1* }/ K( x. k9 }) E
  63.         {& O% s9 S" d2 U. ]
  64.             其他描述符(ACM等)0 \8 k; P, b. b0 i/ d; [
  65.             端点描述符(控制端点)
    ' d8 A" R* j/ [/ E7 O
  66.         }
    4 H% W9 q( K7 k9 |1 k
  67.         接口描述符2
    7 q5 m. H. V3 Q8 ^. J9 P+ V* v
  68.         {
    ; V' |0 H6 ^& L: I% W
  69.             端点描述符(IN)
    + X/ v9 i+ d9 v/ e
  70.             端点描述符(OUT), {: K) g* K! _5 L
  71.         }) g) V2 Q3 c4 `5 T( ^7 A: c  y
  72.     }
    / V9 B  i2 R% E# j8 |* c, D9 W4 R
  73. }
复制代码

  U7 [8 w* K: j! o* B7 P6 l& @/ X( F
  • 配置描述符如下,下面有些字段需要修改的,都用casojie标记了,CTRL+F搜索casojie就可以方便显示;6 D. `8 H# ~6 N5 Q3 p
. i* w: U  X! I- ~
2 U6 d- d& S1 T& R/ {7 t# i
  1. __ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
    $ d8 M5 @' d2 L2 Y! {
  2. {
    ! f' Q4 [& Q6 b7 K
  3.   /*Configuration Descriptor*/
      m/ t' l, e- M1 S4 H- @
  4.   0x09,   /* bLength: Configuration Descriptor size */
    ) q9 c- Y9 D+ k- `1 n
  5.   USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration */
    2 {9 y3 @2 }* Y+ [, `
  6.   USB_CDC_CONFIG_DESC_SIZ,                /* wTotalLength:no of returned bytes */0 D% K( B1 C6 R8 `8 g* T
  7.   0x00,
    * [  U7 h, V$ @2 g/ |, q
  8.   0x0A,   /* bNumInterfaces: 10 interface *///总接口大小,5个CDC*2=10=0x0A casojie
    8 E+ e! x- o) l$ @' ~: e4 @/ F/ B
  9.   0x01,   /* bConfigurationValue: Configuration value */8 \$ P) O! A% g& q* i8 N
  10.   0x00,   /* iConfiguration: Index of string descriptor describing the configuration */; v3 S# r* M8 t& ]5 u
  11.   0xC0,   /* bmAttributes: self powered */
    ' d1 K8 N: k, Z. i
  12.   0x32,   /* MaxPower 0 mA */
    1 k; p" X3 Z# Z- s2 W* S  ?
  13. 5 @2 `7 b6 k% a1 G3 |# s3 ~' ?! H, f
  14.   /*------------------------CDC0--------------------------------------------------8+9+5+5+7+9+7+7-*/: U0 k. L! D& b4 b* D
  15.   // // // IAD  Interface Association Descriptor //IAD描述符需要添加 casojie. a! `: |9 Q3 W9 L- e
  16.   // 0x08,  // bLength: Interface Descriptor size //标识IAD描述符的长度,基本都是8,casojie! A2 P# v. D1 I& l# @
  17.   // 0x0B,      // bDescriptorType: IAD            //不用管
    5 a3 x% x9 S/ w
  18.   // 0x00,  // bFirstInterface                      //第一个接口的序号
    7 u# _) w6 ^6 G5 h; n' y
  19.   // 0x02,  // bInterfaceCount                      //本IDA的接口数量- I& g- @- |8 c2 G3 ~% c, g# p/ b
  20.   // 0x02,  // bFunctionClass: CDC                  //表明该IAD是一个CDC设备6 g$ d$ Q! m5 u* K
  21.   // 0x02,  // bFunctionSubClass                    //不用管
    / v. v! ~" W# e6 B' q6 Q; K
  22.   // 0x01,  // bFunctionProtocol                    //控制协议等其他我也不懂,默认就行- |3 `# ~2 e- \
  23.   // 0x02,  // iFunction    3 s, E* |- i, Q7 F2 X

  24. " U4 k/ t6 L& h9 s6 d/ t
  25. /*Interface Descriptor */$ T2 \0 I& h6 ]5 S$ j2 W# j: j
  26.   0x09,   /* bLength: Interface Descriptor size */. t' u9 o- [, m* V
  27.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    # K/ [" W( R% @9 x. ?( |/ ?( l/ d
  28.   /* Interface descriptor type */
    $ M1 v9 ?2 P+ J2 X, U' S2 C, I
  29.   0x00,   /* bInterfaceNumber: Number of Interface */   //接口编号,从0开始 casojie
    ; ]5 d; ?: ~( m
  30.   0x00,   /* bAlternateSetting: Alternate setting */" T& {, m: c+ A- t
  31.   0x01,   /* bNumEndpoints: One endpoints used */       //接口内有多少个端点被使用 1个 casojie
    - l# b; i' k- i$ i5 H5 R2 @
  32.   0x02,   /* bInterfaceClass: Communication Interface Class */
    - w- f. ?) Q2 b% u! O4 g% m
  33.   0x02,   /* bInterfaceSubClass: Abstract Control Model */6 ]0 R, L9 h9 V3 {
  34.   0x01,   /* bInterfaceProtocol: Common AT commands */
    8 A  m1 ?, [" s* h+ g
  35.   0x00,   /* iInterface: */
    1 r- y# g. L. }5 G( Z
  36. ' R0 Z' \2 g- g; r0 r# a! c5 H
  37.   // /*Header Functional Descriptor*/) `: q2 B4 w) c' P$ }
  38.   // 0x05,   /* bLength: Endpoint Descriptor size */
    % ~1 F1 N6 X6 i. e; m
  39.   // 0x24,   /* bDescriptorType: CS_INTERFACE */1 r* i; ]1 n, q, f6 e; E( E7 X! D9 p2 J
  40.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */2 F& B) Y: S9 b9 Q6 i( ~) B
  41.   // 0x10,   /* bcdCDC: spec release number */0 Y; ~: |- [5 F- n
  42.   // 0x01,
    2 x8 _. w4 Z: L% X- @7 S9 y: r. M3 H# T
  43. % G" ]/ k; y+ B* U, S  u7 `
  44.   // /*Call Management Functional Descriptor*/
    7 f' L& {+ L; V5 v
  45.   // 0x05,   /* bFunctionLength */) v* A' d& ]. {+ m. D  D9 D. Z
  46.   // 0x24,   /* bDescriptorType: CS_INTERFACE */. R3 }( C- g- Z
  47.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */* o/ @( x; H; k# t& o. `3 z
  48.   // 0x00,   /* bmCapabilities: D0+D1 */
    6 E+ M, a  N8 X* o7 |
  49.   // 0x01,   /* bDataInterface: 1 */; q, |* F8 S& r) r) n6 l
  50. 3 U- k9 n4 z2 T  _
  51.   /*ACM Functional Descriptor*/
    , w0 N; j* b: t1 q
  52.   0x04,   /* bFunctionLength */& N2 s1 q. z. M" Y- W5 d
  53.   0x24,   /* bDescriptorType: CS_INTERFACE */  ]+ X# ?5 K2 n" q
  54.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    % r5 @" r  v- Y/ ^
  55.   0x0F,   /* bmCapabilities */2 E+ L4 ]& |$ G, M

  56. . ?: r# ?! c3 S# L0 m. _, I% _0 _0 Z' R
  57.   /*Union Functional Descriptor*/+ ~4 V0 A) z" E% \
  58.   0x05,   /* bFunctionLength */: q# R0 M, G( h% p, V: s! ?
  59.   0x24,   /* bDescriptorType: CS_INTERFACE */. c- v, O0 o  E% o% G5 M+ p
  60.   0x06,   /* bDescriptorSubtype: Union func desc */
    ! \2 [7 V$ T2 g0 v! f9 {# g
  61.   0x00,   /* bMasterInterface: Communication class interface */ //联合描述符,与IAD功能类似,标识哪两个接口是属于一个设备的casojie
    2 J! D8 }, o" c; F/ R% c7 P
  62.   0x01,   /* bSlaveInterface0: Data Class Interface */  //与上面一样,上面是0,这里是1,标识0号,1号接口是属于一个CDC设备的 casojie
    & G" ~& g- y6 O+ [7 N- ]
  63. - |. f' \; b' w5 j* v/ _( \" c0 D
  64.   /*Endpoint 2 Descriptor*/* U) Y# {2 @# K# J% n( c
  65.   0x07,                           /* bLength: Endpoint Descriptor size *///控制端点描述符,虽然端点号是无效的,但是这个描述符不可省略
    # J2 A  i8 g  K- p% O" ~- C
  66.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    # K0 \5 \$ U! [5 F$ D  b* Z
  67.   CDC_CMD_EP,                     /* bEndpointAddress */
    2 `" ?6 C9 v3 k# M- K7 U
  68.   0x03,                           /* bmAttributes: Interrupt */
    & d7 L' S0 B. s1 D! ^7 Z
  69.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    ! f7 e* x2 V9 E! L3 M( i
  70.   HIBYTE(CDC_CMD_PACKET_SIZE)," Y2 g( D6 g/ O! T; g( U
  71.   0x10,                           /* bInterval: */
    ! ^" _  @: d+ b! m
  72.   /*---------------------------------------------------------------------------*/
    / x) r1 }+ j, W$ N3 W2 q0 f

  73. " r/ c# D- C. X1 o# p' R
  74.   /*Data class interface descriptor*/   //第二个接口描述符 casojie
    6 z. ^) C) m, l/ t$ k) G
  75.   0x09,   /* bLength: Endpoint Descriptor size */
    9 S. m* `3 y+ r, @, t
  76.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */( ?0 v. ~1 G3 S! T' d9 t( |$ w' b
  77.   0x01,   /* bInterfaceNumber: Number of Interface */   //接口的序号,上一个接口是0,那这里就是1 casojie
    $ c" P8 p3 L1 |5 T  R1 E
  78.   0x00,   /* bAlternateSetting: Alternate setting */
    . }9 u3 W+ ]0 O  {) v
  79.   0x02,   /* bNumEndpoints: Two endpoints used */       //标识此接口有两个端点(IN)(OUT) casojie- k0 {1 O% u9 c: U5 `3 [
  80.   0x0A,   /* bInterfaceClass: CDC */
    % J' }& S6 p4 \& \, f# Y
  81.   0x00,   /* bInterfaceSubClass: */3 K& @6 T! c# h- {& f
  82.   0x00,   /* bInterfaceProtocol: */
    ! w" V5 }% }& X! X; ?5 l% Y
  83.   0x00,   /* iInterface: */) d; A& V) t/ q0 F" Z

  84. . Z: b) X8 {$ B& ?1 Q( O8 d" }" X$ d; F
  85.   /*Endpoint OUT Descriptor*/                       //OUT端点
    % `6 {* t- L  a, V
  86.   0x07,   /* bLength: Endpoint Descriptor size */
    6 [7 z! R1 t9 o7 b# Q6 F
  87.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */2 B# B0 J: w+ d9 N2 \" P. h
  88.   CDC_OUT_EP,                        /* bEndpointAddress */
    ( s5 a8 r: c4 T* n+ R
  89.   0x02,                              /* bmAttributes: Bulk */1 l* X! o  W5 w1 G8 t# x  }
  90.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */$ {6 y# p) j; [( B- ~
  91.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    9 b7 u. g9 a, F, o
  92.   0x00,                              /* bInterval: ignore for Bulk transfer */5 b% V& g8 A6 Y" X+ F

  93. # O& c" s8 u+ D6 ?0 T; F
  94.   /*Endpoint IN Descriptor*/                        //IN端点
    8 ^" A( K7 ~# H& Q7 |
  95.   0x07,   /* bLength: Endpoint Descriptor size */3 W1 d( P& C$ s+ [( m6 o# H
  96.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    / _8 v/ x5 i$ T* G7 I) W' |3 x
  97.   CDC_IN_EP,                         /* bEndpointAddress */, |# Q* C& `, e
  98.   0x02,                              /* bmAttributes: Bulk */$ ?+ n0 S3 l# _. o8 a2 c5 ?
  99.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */9 {+ H% L6 N6 G; f. U
  100.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0 C3 u" u% G% [+ d) N8 P; [
  101.   0x00,                               /* bInterval: ignore for Bulk transfer */
    : b- S$ Z( H4 f& Q( Y, l0 }
  102. , {: ?+ a& V: V& y  A
  103.   /*---------------------------------------------------------------------------*/
    & n, U, v# {6 U. Q
  104.   // IAD  Interface Association Descriptor       //这里就是CDC1了,重复CDC0的配置过程,注意有些字段的序号 casojie
    - m+ E. p& n4 L4 b2 M8 f; w: v
  105.   // 0x08,  // bLength: Interface Descriptor size6 O" P: x' O, O$ E; J2 a& ?' Q+ Y  {
  106.   // 0x0B,      // bDescriptorType: IAD
    2 x/ D1 e" I9 @8 ^1 m# c
  107.   // 0x02,  // bFirstInterface                  //太多了,写不下去了,意思和第一个IDA一样的
    6 R( `$ s; p) {: H  g2 {0 C$ z
  108.   // 0x02,  // bInterfaceCount
    1 P; @; n; R# w/ T- m7 C" M
  109.   // 0x02,  // bFunctionClass: CDC# J! w6 L+ b( j, H2 _9 {
  110.   // 0x02,  // bFunctionSubClass1 \# I8 L) s" \2 u# O9 p4 e2 ~6 l# W
  111.   // 0x01,  // bFunctionProtocol " G! k  B- ~* @0 C. G, |1 v3 {
  112.   // 0x02,  // iFunction
    + x9 }6 A1 S+ g! T* M
  113. $ f: L$ {  h  K. I$ c
  114. /*Interface Descriptor */* `" t. @' _0 U6 c. q6 v! H
  115.   0x09,   /* bLength: Interface Descriptor size */. A# i7 P% Y9 W0 F
  116.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    + M7 {: J" }) u: l2 q2 ], A
  117.   /* Interface descriptor type */
    2 `/ A  ]" g; M0 @6 `7 p
  118.   0x02,   /* bInterfaceNumber: Number of Interface */
    4 \$ w5 H/ Y, S( H5 H1 ?
  119.   0x00,   /* bAlternateSetting: Alternate setting */
    + [1 T8 d5 t( X2 m# m
  120.   0x01,   /* bNumEndpoints: One endpoints used */; O5 h6 y6 M; f  K( r
  121.   0x02,   /* bInterfaceClass: Communication Interface Class */! [% B3 f7 q* c8 j! u$ K8 w) g
  122.   0x02,   /* bInterfaceSubClass: Abstract Control Model */* g( q% [8 I, L9 o6 ]. g
  123.   0x01,   /* bInterfaceProtocol: Common AT commands */
    + n4 N9 \* w4 P& u8 W' ?' e& X0 L
  124.   0x00,   /* iInterface: */
    , H% h/ Y1 P# w2 }

  125. 4 m' R- m2 h5 h  [/ l
  126.   // /*Header Functional Descriptor*/
    7 h+ i3 l5 ^0 }2 t' m
  127.   // 0x05,   /* bLength: Endpoint Descriptor size */
    , d# D. R4 |* t" r0 c! i
  128.   // 0x24,   /* bDescriptorType: CS_INTERFACE */' J# w, Q0 b& B" Z, n; \- ?
  129.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */. f! Y2 k2 Z( B' C( J, ~
  130.   // 0x10,   /* bcdCDC: spec release number */) u$ E/ i! C( Q9 z: I
  131.   // 0x01,
    * f, G  r+ c# f6 \6 o% X: A: h
  132. $ s( X$ R0 a5 {
  133.   // /*Call Management Functional Descriptor*/$ g' _% d" e. i# t& m" ?
  134.   // 0x05,   /* bFunctionLength */
    * C5 M6 y$ T3 P. Q- _: B7 f2 p3 g
  135.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
    9 [9 V0 p$ K$ x
  136.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */: m8 U+ e0 }1 ?6 Z1 O* s7 ^
  137.   // 0x00,   /* bmCapabilities: D0+D1 */( o- ]7 _' ^, q: W' p) v2 j9 a
  138.   // 0x01,   /* bDataInterface: 1 */
    0 i- _1 X; X7 D! H" V2 Z7 `
  139. 6 N  m1 I" u' M: T$ A3 ^
  140.   /*ACM Functional Descriptor*/5 O& }/ Y/ }- q( D5 Z2 L  ^% L) g; Q0 N
  141.   0x04,   /* bFunctionLength */( K5 s% ]) [9 D9 I, c
  142.   0x24,   /* bDescriptorType: CS_INTERFACE */, l" a( x  _# r3 Q
  143.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */3 h. e: ?# C% b
  144.   0x0F,   /* bmCapabilities */% k' \3 k# o. I1 r) K$ M  |
  145. / [3 R8 L: `1 f6 E; C. q
  146.   /*Union Functional Descriptor*/9 ^2 \5 M/ H6 a' U$ r; X
  147.   0x05,   /* bFunctionLength */
    5 s; x% @/ Z9 m0 l; T+ T- b2 b
  148.   0x24,   /* bDescriptorType: CS_INTERFACE */
    * v, E# O; I: P3 n* L0 [
  149.   0x06,   /* bDescriptorSubtype: Union func desc */$ j$ Y$ F8 h( N/ d" c
  150.   0x02,   /* bMasterInterface: Communication class interface */
    ' g4 U( G+ a% z- b7 s# W; N  {- Z
  151.   0x03,   /* bSlaveInterface0: Data Class Interface */
    : C& D5 v& ]1 d& C: z, h4 i

  152. 4 v- @# l1 |; H2 w  C
  153.   // /*Endpoint 2 Descriptor*/5 z2 g& i6 C* h1 J& S: O
  154.   0x07,                           /* bLength: Endpoint Descriptor size */
    8 d, V' B4 x; j/ y6 E( m& l
  155.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    3 f3 E; Q  Q, Q
  156.   CDC_CMD_EP1,                     /* bEndpointAddress */
    # V# v7 y* h/ [' M5 v  o
  157.   0x03,                           /* bmAttributes: Interrupt */0 Q5 L4 Q5 A/ A, F
  158.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */, q- k' y: X$ p7 @# u6 s$ K) m
  159.   HIBYTE(CDC_CMD_PACKET_SIZE),2 m* x9 D+ M9 P1 U* S- V  p/ O
  160.   0x10,                           /* bInterval: */
    ) n4 D9 l! E! u$ w4 K" Y# w" @
  161.   /*---------------------------------------------------------------------------*/
    : K/ s, _( R  v! c! n% n4 l1 x1 t3 F# q
  162. ; t7 ?( M# U/ N) b  [
  163.   /*Data class interface descriptor*/
    & L# O2 {- I4 \# t# p- }  P2 x6 \
  164.   0x09,   /* bLength: Endpoint Descriptor size */& P& M) i  f& v. S3 `/ a- f9 R# b
  165.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */, B$ u$ s: @# k9 o$ k9 t: c
  166.   0x03,   /* bInterfaceNumber: Number of Interface */0 ~+ @, r# }7 K% q, t8 L, z9 f; r
  167.   0x00,   /* bAlternateSetting: Alternate setting */% B1 X) }- J9 V
  168.   0x02,   /* bNumEndpoints: Two endpoints used */
    9 E$ E7 Z4 _0 M  l. k* K
  169.   0x0A,   /* bInterfaceClass: CDC */9 I; k1 E  H+ A/ @& h9 l" @$ p
  170.   0x00,   /* bInterfaceSubClass: */7 P+ m) s- m' B) ^  S( f
  171.   0x00,   /* bInterfaceProtocol: */
    ; f; ?- m8 p" J- J- n1 p3 \
  172.   0x00,   /* iInterface: */8 u1 D/ O  ?5 I; ~

  173. ! w( J  Q  ^3 \8 B2 J6 i
  174.   /*Endpoint OUT Descriptor*/
    9 f+ u. G  A9 [: k+ I: H
  175.   0x07,   /* bLength: Endpoint Descriptor size */
    - T8 H4 M6 A/ Y1 r
  176.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */! M1 W4 L( w8 u9 B8 S" b
  177.   CDC_OUT_EP1,                        /* bEndpointAddress */
    ) S- Q. }5 O% z$ J* k  v
  178.   0x02,                              /* bmAttributes: Bulk */
    : z" H, b$ O$ i
  179.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    " k: N# S# f, ^" V) A( h4 i, X
  180.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),' y3 T* l; g7 v6 U7 r* h
  181.   0x00,                              /* bInterval: ignore for Bulk transfer */% q/ D! u, f+ {

  182. " U8 h: `# d3 t) A2 n' k& w* E. W3 n
  183.   /*Endpoint IN Descriptor*/
      ?9 s/ a( l5 w# Q: m  m. V7 D7 k; k' B
  184.   0x07,   /* bLength: Endpoint Descriptor size */
    ; x1 V& W. R6 K* V
  185.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    ) o4 }& d$ v$ B6 q1 I, Z
  186.   CDC_IN_EP1,                         /* bEndpointAddress */
    ) m8 Y5 c+ O) I- E+ e! z- l4 [9 Z! T
  187.   0x02,                              /* bmAttributes: Bulk */
    * o3 z: n5 O2 {% a! z7 A: q
  188.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    1 X) L* k, w; W9 h/ m* b( E
  189.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),* f- y5 a1 ~3 T' U7 B, |
  190.   0x00,                               /* bInterval: ignore for Bulk transfer */8 i: F$ v& J4 w1 B3 {, z
  191.   /*---------------------------------------------------------------------------*/
      l' p# B2 v% e) W' n
  192.   // IAD  Interface Association Descriptor
    " \0 |, s2 _8 U1 f/ G. |( U
  193.   // 0x08,  // bLength: Interface Descriptor size0 z2 U6 o$ t) d: x: n+ o, }
  194.   // 0x0B,      // bDescriptorType: IAD5 R9 z: }! ^& ]
  195.   // 0x04,  // bFirstInterface: y# V9 ^/ F, d2 O
  196.   // 0x02,  // bInterfaceCount
    - j- ^6 k! T; V: o/ {$ G
  197.   // 0x02,  // bFunctionClass: CDC3 O5 I& F# Z# A7 p
  198.   // 0x02,  // bFunctionSubClass
    * Z$ |  s, U- l, X, E" o* ], U8 p
  199.   // 0x01,  // bFunctionProtocol
    8 u8 E) v% B  \  o4 Z9 x- _' P6 V3 L
  200.   // 0x02,  // iFunction
    ! a8 I* k* K! h% t; v: b* `
  201. ' N4 y: g, U, G
  202. /*Interface Descriptor */
    $ c2 i* h" |/ g: O
  203.   0x09,   /* bLength: Interface Descriptor size */
    7 B: ~. W6 w0 I9 _
  204.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    5 k1 q( @! D: F8 ^+ }8 F! p
  205.   /* Interface descriptor type */
    ) F' Q6 F* g  h" _( G
  206.   0x04,   /* bInterfaceNumber: Number of Interface */' v% Z$ C6 ]- J5 H5 V
  207.   0x00,   /* bAlternateSetting: Alternate setting */
    . U- [: v. T3 S5 r0 |3 [  H1 h
  208.   0x01,   /* bNumEndpoints: One endpoints used */% x9 B7 S% P- ?+ O
  209.   0x02,   /* bInterfaceClass: Communication Interface Class */9 F" X8 X8 W4 k* f" b! C3 C
  210.   0x02,   /* bInterfaceSubClass: Abstract Control Model */4 ?3 U  k  C5 s* ?
  211.   0x01,   /* bInterfaceProtocol: Common AT commands */
    ( `! K& [0 y9 ?: M) x8 X! ~' H
  212.   0x00,   /* iInterface: */7 v8 L9 v0 T- j/ F  i& l
  213. 4 B" |0 L  i( o+ J( b! U- b
  214.   // /*Header Functional Descriptor*/8 I/ ]" n/ J* Y- `" B8 ^$ J/ Y* I
  215.   // 0x05,   /* bLength: Endpoint Descriptor size */
    ) ^' {9 ?3 g3 d
  216.   // 0x24,   /* bDescriptorType: CS_INTERFACE */4 s1 e' \( E2 j4 R1 E& w; g" r6 O1 X- t
  217.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */
    + V  F; u7 X. {( V+ A
  218.   // 0x10,   /* bcdCDC: spec release number */
    3 H2 Y4 Q0 W0 Q) S
  219.   // 0x01,7 @' @1 Z9 K- C$ L1 k& }! v

  220. : q, b- j" g6 ~2 ~) }/ L
  221.   // /*Call Management Functional Descriptor*/
    0 ]0 L+ G2 M% s1 \# D6 ~
  222.   // 0x05,   /* bFunctionLength */
    - a  d  x* M3 p, c/ |' H
  223.   // 0x24,   /* bDescriptorType: CS_INTERFACE */$ H. n# P, |8 z! s  c; x
  224.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */, f7 c0 Z% `+ s9 g% P3 y" w9 f+ f
  225.   // 0x00,   /* bmCapabilities: D0+D1 */
    5 i- R8 \4 j% @+ q
  226.   // 0x01,   /* bDataInterface: 1 */
    5 ~; N2 H! I; T

  227. ; F  t4 f5 E2 Q/ S
  228.   /*ACM Functional Descriptor*/% R/ s3 p3 i, t$ u7 j
  229.   0x04,   /* bFunctionLength */
    ) H9 h. R2 K: T. O6 N5 i
  230.   0x24,   /* bDescriptorType: CS_INTERFACE */6 K8 J9 z" ?/ s9 \4 V# W0 @
  231.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    * }; e: R9 V5 r9 j7 X3 W
  232.   0x0F,   /* bmCapabilities */8 [" h, }$ x& ]( N2 W( j0 s
  233. 8 Q* F# P" ]' \" {) z& |+ v
  234.   /*Union Functional Descriptor*/
    . O% d# ?) _; {( T
  235.   0x05,   /* bFunctionLength */8 p7 p. X# R# \
  236.   0x24,   /* bDescriptorType: CS_INTERFACE */
    4 Q/ x$ D& h  Z2 g5 N  N' ^" |9 S
  237.   0x06,   /* bDescriptorSubtype: Union func desc */
    : {& @  p# x- S7 g6 `7 n7 X& `! w
  238.   0x04,   /* bMasterInterface: Communication class interface */
    + f3 A( `  L8 w. P
  239.   0x05,   /* bSlaveInterface0: Data Class Interface */0 |* a6 h: W, q

  240.   o/ z7 {+ m& a. H- P3 ?0 i
  241.   // /*Endpoint 2 Descriptor*/- l( k, _9 k" K3 z! s* z
  242.   0x07,                           /* bLength: Endpoint Descriptor size */- _( E' F  y, w! V, y
  243.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    - ?8 E/ }6 l1 j" P1 f
  244.   CDC_CMD_EP2,                     /* bEndpointAddress */
    4 n$ W: E8 D( y$ P
  245.   0x03,                           /* bmAttributes: Interrupt */
    1 f7 |3 i4 d- P
  246.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    3 r* y1 b9 e9 s  _! \
  247.   HIBYTE(CDC_CMD_PACKET_SIZE),
    2 Q  g; R7 f; \% e! d4 x
  248.   0x10,                           /* bInterval: */
    6 }  ~0 J* L" ^9 ]* h0 F3 ]8 J
  249.   /*---------------------------------------------------------------------------*/9 J9 n% V* h$ _
  250. & d* V8 p. e9 P. o4 A
  251.   /*Data class interface descriptor*/
    " ^( d/ i0 O6 G& C- ~) [, A
  252.   0x09,   /* bLength: Endpoint Descriptor size */
    # S! i0 [( O' Q) h8 V
  253.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    3 ?* t0 e) k8 M9 Z5 o
  254.   0x05,   /* bInterfaceNumber: Number of Interface */
    / J2 ^1 B7 G- M: c
  255.   0x00,   /* bAlternateSetting: Alternate setting */
    4 e0 i8 i5 L( v9 X1 b
  256.   0x02,   /* bNumEndpoints: Two endpoints used */
    4 @/ z. k& g7 {0 l# s3 L$ \. m5 O
  257.   0x0A,   /* bInterfaceClass: CDC */. w$ U5 o" @7 Q4 d7 N
  258.   0x00,   /* bInterfaceSubClass: */
    1 ^. J+ [7 B/ p
  259.   0x00,   /* bInterfaceProtocol: */" _- P8 R' i- K' D
  260.   0x00,   /* iInterface: */
    $ i& y9 D% F& k7 M% I# _6 i) V
  261. , F9 m' `7 q& L7 R( B. H# v, e: L
  262.   /*Endpoint OUT Descriptor*/
    5 ~! y* h$ C7 S5 z% a& _3 @. i
  263.   0x07,   /* bLength: Endpoint Descriptor size */6 d# T# v+ A3 U7 }4 a
  264.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    9 z: V$ P7 {* _5 d+ d3 ]
  265.   CDC_OUT_EP2,                        /* bEndpointAddress */. r/ E; |) v& o: e9 @
  266.   0x02,                              /* bmAttributes: Bulk */* c  ?8 f: n: U# w& P0 m0 e# E
  267.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    ! }. {3 Z+ E7 e2 g
  268.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),2 u# p" O: s; P. F6 t5 `9 ?
  269.   0x00,                              /* bInterval: ignore for Bulk transfer */
    ! q  }( r1 T& T7 U+ p

  270. ( s' p$ o. n, a! R5 C
  271.   /*Endpoint IN Descriptor*/
    3 X8 _7 C7 e$ }+ N3 p& X" U
  272.   0x07,   /* bLength: Endpoint Descriptor size */
    2 e8 R& o5 \% W! R8 V: c
  273.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */- y$ P+ b$ i; m% Y6 @. l" c! g$ a8 k
  274.   CDC_IN_EP2,                         /* bEndpointAddress */8 T) B9 E2 E3 Z9 q, I' @
  275.   0x02,                              /* bmAttributes: Bulk */7 K7 r- G9 b8 e  _, K  k
  276.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    ! |' J1 S9 c/ x* E3 M  P
  277.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  e0 P6 |" P  q* h' Y
  278.   0x00,                               /* bInterval: ignore for Bulk transfer */
    4 `8 q. |, T: ?

  279. / L/ d- {1 H( L# `/ G% p
  280.   /*---------------------------------------------------------------------------*/
    * P: O- s+ l- N/ v
  281.   // IAD  Interface Association Descriptor0 [+ @9 h! b) R4 c. i9 H; L& {
  282.   // 0x08,  // bLength: Interface Descriptor size6 @: W, ]- M) s  {% e) A- C. V
  283.   // 0x0B,      // bDescriptorType: IAD, P# ]( \% i2 O1 e7 s- C# G, p
  284.   // 0x06,  // bFirstInterface5 R; \' b! J# \% k  u
  285.   // 0x02,  // bInterfaceCount- d# i  P% K; p: m1 A: a
  286.   // 0x02,  // bFunctionClass: CDC
    & |. T, j8 `4 L1 O% s
  287.   // 0x02,  // bFunctionSubClass
    % g, E# _$ F% i
  288.   // 0x01,  // bFunctionProtocol ! I" }/ \, J% N; |# Y
  289.   // 0x02,  // iFunction
    ) ?1 y# m$ }! ~( x- J9 W9 _
  290. 9 P; P0 ^* w  ]( U& u/ q. A0 u
  291. /*Interface Descriptor */
    & w+ U/ e+ J- G) H; J3 y! k, p
  292.   0x09,   /* bLength: Interface Descriptor size */
    ( n, k5 `2 C  R. N5 b3 d
  293.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    . u0 i* p! @" a# I
  294.   /* Interface descriptor type */; M( L+ k8 ~9 F
  295.   0x06,   /* bInterfaceNumber: Number of Interface */+ F7 D. W6 B+ f0 n* {* ^
  296.   0x00,   /* bAlternateSetting: Alternate setting */# ~  Z* }! b8 Z4 C8 C
  297.   0x01,   /* bNumEndpoints: One endpoints used */( U  A6 F* p* c4 v
  298.   0x02,   /* bInterfaceClass: Communication Interface Class */9 _) U2 }% }. ]) v
  299.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    2 E/ o# G* e0 U0 R# Q- H0 p
  300.   0x01,   /* bInterfaceProtocol: Common AT commands */- j' V. K8 {8 q/ I% q
  301.   0x00,   /* iInterface: */
    9 }- y! t% I. B0 X/ E4 d
  302. ! J1 W6 e( {  ]  L6 r6 S/ Z
  303.   // /*Header Functional Descriptor*/
    3 M" D, {7 O4 x5 m, ^, O
  304.   // 0x05,   /* bLength: Endpoint Descriptor size */2 l- Z1 q+ E! i+ o7 D
  305.   // 0x24,   /* bDescriptorType: CS_INTERFACE */3 Z* l+ M2 P' X9 ~6 d
  306.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */
    ) N/ D7 \& ~4 T. j* S) j
  307.   // 0x10,   /* bcdCDC: spec release number */
    9 z0 F) G7 n7 D3 A$ Q# q0 t
  308.   // 0x01,) W$ |/ C' b$ {) J8 l! K

  309. . R6 W7 S+ s  t9 p7 M3 P8 z: J
  310.   // /*Call Management Functional Descriptor*/
    " f( M; u/ [2 m
  311.   // 0x05,   /* bFunctionLength *// P# j. O; l3 S; y2 b4 x
  312.   // 0x24,   /* bDescriptorType: CS_INTERFACE */2 S8 K) f0 b7 _# c0 a4 d
  313.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */4 N, s0 a: T! T. R& [7 u
  314.   // 0x00,   /* bmCapabilities: D0+D1 */
    6 Z2 u$ r1 h2 }3 i* j6 Y2 R
  315.   // 0x01,   /* bDataInterface: 1 */
    4 H# ]2 `, [4 z# F- C
  316. - A# g; @/ \( {, h0 s+ N. X
  317.   /*ACM Functional Descriptor*/
    , \" P3 H3 i8 r7 M# R/ R/ Q1 y+ `
  318.   0x04,   /* bFunctionLength */* x% F4 z$ z6 g7 l7 X; P" P
  319.   0x24,   /* bDescriptorType: CS_INTERFACE */  w! q4 [9 ^/ Y8 [) Z# l
  320.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    1 `! y& \* t9 L& J5 k4 F; x
  321.   0x0F,   /* bmCapabilities */
    . P1 `8 g% E' O
  322. * B) H, F% m8 a/ ?+ a! X+ b& a+ k
  323.   /*Union Functional Descriptor*/
    * @. `8 C8 O+ [
  324.   0x05,   /* bFunctionLength */! A6 t8 Y* @& F+ I
  325.   0x24,   /* bDescriptorType: CS_INTERFACE */& j9 B7 }) C$ `, Y% A) z
  326.   0x06,   /* bDescriptorSubtype: Union func desc */
    ( q0 n' L, Y: U: f, r# w. Q. v" w
  327.   0x06,   /* bMasterInterface: Communication class interface */! z# w# m3 x; M0 A7 [0 o
  328.   0x07,   /* bSlaveInterface0: Data Class Interface */5 i  z2 x8 b3 h6 Z" y& p

  329. 5 p* Z; }0 D4 T6 j
  330.   /*Endpoint 2 Descriptor*/: B# N$ g0 \& D1 A* Q0 Y
  331.   0x07,                           /* bLength: Endpoint Descriptor size */
    & H( W. f! ^& s" [5 v# J1 E8 H6 B
  332.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    , h6 E8 j$ I9 W& s0 x' v. |- n
  333.   CDC_CMD_EP3,                     /* bEndpointAddress */4 w6 t9 q  _, W4 b# g+ h
  334.   0x03,                           /* bmAttributes: Interrupt */
    ; E2 W; m  E5 i0 y; C5 R
  335.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    1 D( [6 J3 J2 O& r9 d9 l
  336.   HIBYTE(CDC_CMD_PACKET_SIZE),4 j5 V$ u! m1 ?5 |
  337.   0x10,                           /* bInterval: */
    # Q7 u6 W4 v/ ]# Q
  338.   /*---------------------------------------------------------------------------*/! @7 J8 c- Z1 [& d
  339. ( ~8 A4 g' ^! _2 ]# @; m
  340.   /*Data class interface descriptor*/$ _$ Z; y% E: }- L- A  D8 J! O
  341.   0x09,   /* bLength: Endpoint Descriptor size */$ Z4 p7 p& z4 J
  342.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */" T7 d# w( S0 V. U. |% e' Q0 T
  343.   0x07,   /* bInterfaceNumber: Number of Interface */
      j! {& K( G0 S; s$ a
  344.   0x00,   /* bAlternateSetting: Alternate setting */
    . t4 e- T8 J* x  d
  345.   0x02,   /* bNumEndpoints: Two endpoints used */% _* N3 ]( h# j7 u
  346.   0x0A,   /* bInterfaceClass: CDC */1 J4 @7 P9 {& S* c* Q: V4 u
  347.   0x00,   /* bInterfaceSubClass: */
    0 V& s( s8 F% {0 I3 {% Y
  348.   0x00,   /* bInterfaceProtocol: */8 N1 h$ u2 K) t
  349.   0x00,   /* iInterface: */
    9 @' w( @4 C6 f# R' h! h

  350. ; J. s) i' T+ K4 t0 j; n
  351.   /*Endpoint OUT Descriptor*/( d* M' |7 L2 u+ Z. @1 F$ ^. g
  352.   0x07,   /* bLength: Endpoint Descriptor size */
    1 `/ w2 U# P: G! X$ P7 i! b
  353.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    5 F$ u+ Z) x4 q7 S0 E* }: F. d
  354.   CDC_OUT_EP3,                        /* bEndpointAddress */8 ]/ q) g- G5 f) p' R+ {
  355.   0x02,                              /* bmAttributes: Bulk */! R1 B# u  y8 ?( D/ {; d
  356.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */, [. S" e' d) u, C! I; E
  357.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),* y$ k+ I6 P* e
  358.   0x00,                              /* bInterval: ignore for Bulk transfer */
      |1 k3 f1 x( J

  359. 4 W; W/ i  m# {9 S* T  n+ F
  360.   /*Endpoint IN Descriptor*// \" N8 D: ?2 Q2 @9 H4 j) I5 K
  361.   0x07,   /* bLength: Endpoint Descriptor size */
    0 F( ]) u. V9 n% f2 P) f" b% @0 [
  362.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    ; M: C3 s: X" [* j
  363.   CDC_IN_EP3,                         /* bEndpointAddress */
      }+ C4 u3 i+ H1 U( J
  364.   0x02,                              /* bmAttributes: Bulk */! w+ y8 y, }+ `" q
  365.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    7 N& S% J1 R! f4 T, t5 G0 ~
  366.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    1 F; E, U" c* ?
  367.   0x00,                               /* bInterval: ignore for Bulk transfer */
    1 b, [, v+ t4 u( Y9 _
  368. " x3 O3 o4 f; l2 [
  369. //   /*---------------------------------------------------------------------------*/7 Y  X& P/ j8 p5 I! n
  370. //   // IAD  Interface Association Descriptor
    3 z/ ^5 L0 H+ b1 E, G2 B
  371. //   // 0x08,   // bLength: Interface Descriptor size  ~. n. D6 {# q; A
  372. //   // 0x0B,       // bDescriptorType: IAD
    5 b4 O9 d8 c; g7 h
  373. //   // 0x08,   // bFirstInterface: \. ]9 l( Z  r4 ?; C9 j" r
  374. //   // 0x02,   // bInterfaceCount; T1 v* E8 K* X5 |' D
  375. //   // 0x02,   // bFunctionClass: CDC
    5 q2 b  I7 P7 b% E& g, K) u
  376. //   // 0x02,   // bFunctionSubClass
    0 c0 h5 t8 i+ n. Q
  377. //   // 0x01,   // bFunctionProtocol 7 j, _$ }+ i' k7 X1 z* n+ ?
  378. //   // 0x02,   // iFunction: p- j! R$ I& A. j

  379. 4 _: K. ^/ u0 H% n$ A4 M7 k
  380. /*Interface Descriptor */
    8 M$ Z+ E2 r: Z- E
  381.   0x09,   /* bLength: Interface Descriptor size */
    0 w, J! L: ]2 g1 K! j7 t& p
  382.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */7 A+ x& E3 O0 r2 g2 `6 E
  383.   /* Interface descriptor type */. Y2 ~  _' g0 ?$ [- \, z3 U- x
  384.   0x08,   /* bInterfaceNumber: Number of Interface */8 r9 N( j+ S% q# s9 G8 o" P
  385.   0x00,   /* bAlternateSetting: Alternate setting */% v" g+ N0 ]  y3 L4 c1 u
  386.   0x01,   /* bNumEndpoints: One endpoints used */
    % a6 V) s3 V% w5 H7 h! X) j
  387.   0x02,   /* bInterfaceClass: Communication Interface Class */# w4 H$ r3 g5 {9 u! R1 R5 L: r" G
  388.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    - u0 e. x8 H6 _6 v
  389.   0x01,   /* bInterfaceProtocol: Common AT commands */5 W% i; c3 p: J9 Q5 f  u8 y
  390.   0x00,   /* iInterface: */
    / v! Y" i! s: }% ~' v* e  }4 T

  391. 5 r: L# @* Q3 f/ \
  392.   // /*Header Functional Descriptor*/
    8 \/ R( `1 s6 p( |4 a1 {& E
  393.   // 0x05,   /* bLength: Endpoint Descriptor size */
    2 y3 ?0 e; E* D
  394.   // 0x24,   /* bDescriptorType: CS_INTERFACE */% R9 @+ j: b' B1 c' ]$ e
  395.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */; _* M1 }  ]) I3 @  {8 l3 \
  396.   // 0x10,   /* bcdCDC: spec release number */
    " a  r$ o6 M% H3 o9 `4 \
  397.   // 0x01,) N' [$ B3 v. m/ c$ A- Y* X* ^5 h
  398. 0 h  z' u3 w8 L( W& c- T& c
  399.   // /*Call Management Functional Descriptor*/
    7 j3 }% `: A5 f+ L2 i1 o8 ]9 [) P
  400.   // 0x05,   /* bFunctionLength */+ S$ j  y0 Z) v3 T, z& h, C- [8 K0 {
  401.   // 0x24,   /* bDescriptorType: CS_INTERFACE */, R; }/ N+ x: d! d3 [
  402.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */3 h/ s* N8 P% K' p5 }
  403.   // 0x00,   /* bmCapabilities: D0+D1 */
    6 R! C& ], u$ Z, A
  404.   // 0x01,   /* bDataInterface: 1 */
    % }1 P& B( b+ n2 i( I0 m

  405. " O1 U/ c# j8 a% k* z
  406.   /*ACM Functional Descriptor*// G4 [, j$ u' U% b9 J
  407.   0x04,   /* bFunctionLength */6 x- i3 \& ~/ u( ^
  408.   0x24,   /* bDescriptorType: CS_INTERFACE */, h( B0 E" ?9 u( I9 p7 C( r7 p
  409.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */" h( L  l4 ?) d: @( s! @) a% ]
  410.   0x0F,   /* bmCapabilities */
    % D/ Z9 X- \/ D2 ^  B6 w5 E1 ^

  411. . X/ c2 R0 a3 o
  412.   /*Union Functional Descriptor*/) h, X- c, }, ^
  413.   0x05,   /* bFunctionLength */
    8 z8 r2 t2 Q! `7 o( y' }' g, ^. l
  414.   0x24,   /* bDescriptorType: CS_INTERFACE */
    , ~( T! r$ o% x* s
  415.   0x06,   /* bDescriptorSubtype: Union func desc */6 C! c0 m3 i6 P. P  Z& r4 }
  416.   0x08,   /* bMasterInterface: Communication class interface */; w& V8 x3 Q; ~
  417.   0x09,   /* bSlaveInterface0: Data Class Interface */. x" M/ |( i3 R  J+ k

  418. * h% V+ [, ]2 v3 U3 @9 w. i
  419.   /*Endpoint 2 Descriptor*/
    . Y* c( m' Y: C, O7 u* I3 G" P6 a/ n
  420.   0x07,                           /* bLength: Endpoint Descriptor size */5 C+ H+ X+ l, g. O/ ?; I6 N5 I- S; B" M
  421.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint *// \) O1 p" e3 q/ @+ R: p3 k9 h  {
  422.   CDC_CMD_EP4,                     /* bEndpointAddress */+ G5 s. j+ F+ d' n* r7 u/ j# u! g6 d3 b
  423.   0x03,                           /* bmAttributes: Interrupt */2 _0 L8 D8 f$ B/ t6 _7 ]
  424.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    " Y  a* l" V) [  d7 a: m3 h
  425.   HIBYTE(CDC_CMD_PACKET_SIZE),
    ' T2 L+ s& g! n+ R/ k0 v. K2 ~7 c
  426.   0x10,                           /* bInterval: */ $ I7 p+ R3 F8 t! B7 |# }
  427.   /*---------------------------------------------------------------------------*/
    & K# Z/ ]5 s0 q, ]/ ]3 s
  428.   /*
    ; e: T% r* }8 ?! G2 s
  429.   /*Data class interface descriptor*/
    - J) f  Q! H) ^$ Q( ?! v: u
  430.   0x09,   /* bLength: Endpoint Descriptor size */
    " y- X" \% x( l3 B
  431.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: *// v1 D% y7 X9 Y2 ?
  432.   0x09,   /* bInterfaceNumber: Number of Interface */' w- Y8 z1 l2 D- W# i  _
  433.   0x00,   /* bAlternateSetting: Alternate setting */
    8 w& U/ c4 {5 P  _7 E
  434.   0x02,   /* bNumEndpoints: Two endpoints used */
    # a' Q4 S0 ~5 w$ K4 j$ j' a
  435.   0x0A,   /* bInterfaceClass: CDC */
    ! D6 S/ H; D  {  Q
  436.   0x00,   /* bInterfaceSubClass: */
    / h6 ?! e( Y0 p
  437.   0x00,   /* bInterfaceProtocol: */
    % u- i' r+ D# H% t, x5 I
  438.   0x00,   /* iInterface: */
    6 N% w9 O$ m1 R& q8 d/ m( K
  439. , Z$ _9 e3 ^: `
  440.   /*Endpoint OUT Descriptor*/( y7 _' |: \1 X. ^3 o2 S% O
  441.   0x07,   /* bLength: Endpoint Descriptor size */: ?, P8 q1 S4 r# N; C+ }$ R
  442.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */# G: S0 r+ ]  Y; @4 J2 t
  443.   CDC_OUT_EP4,                        /* bEndpointAddress */% ?6 p. m1 K2 W  A9 R1 S
  444.   0x02,                              /* bmAttributes: Bulk */: N, ^( W1 K5 v& h
  445.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */: h, M# c/ e" j6 |$ |( }. F
  446.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    4 \; i  X9 c6 I8 @% x
  447.   0x00,                              /* bInterval: ignore for Bulk transfer */
    # ?+ V- w0 P, y( B0 j

  448. ( X0 h8 f4 [3 Y7 J& d
  449.   /*Endpoint IN Descriptor*/* b  N5 y. r4 ~+ j
  450.   0x07,   /* bLength: Endpoint Descriptor size */
    ) j) `. o6 _2 Q  e7 O/ t. V
  451.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */' B3 v7 B: K: `9 f
  452.   CDC_IN_EP4,                         /* bEndpointAddress */
    + C  D7 @$ t# H
  453.   0x02,                              /* bmAttributes: Bulk */- S- y: z3 w# m* h* p
  454.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    " F- d7 @6 c8 p. A* ?) n
  455.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    ; J$ i! I7 ~0 q* S& `
  456.   0x00                               /* bInterval: ignore for Bulk transfer */ , Z6 B; z1 V% f4 D. J
  457. }
复制代码
% z% T. x; Q. k+ I" C

0 j' H. c8 Y7 \) G/ K: P* }
  • 为什么上面有些描述符被注释掉了?
  • 配置5个CDC如果描述符都写上了,这个结构体就超过了255个字节大小,超过了USB2.0最大配置描述符长度
  • 在我的项目中,IAD和联合描述符(/Union Functional Descriptor/)功能一样,我这里注释IAD描述符,不会影响USB,但在windows平台下,它认的是IAD描述符,这个时候就可以注释联合描述符,打开IAD描述符,总之,省略一些非必要描述,减少长度
    ) _2 }" h" D# ^& V
  • 这里的坑很多很多,需要很耐心,配错一个字段,千奇百怪的问题就来了) s, r8 q. A# g; k/ p
    2 p8 b4 p8 t* s8 c9 K
3.4 配置PMA---USB硬件缓存
  • 这里又有坑了,我把我知道的都说出
    7 @0 o3 D; f" n4 |% w
3.4.1 PMA是啥?
  • 此部分感谢一个大佬的帖子,理解来源与它
  • 这个PMA的作用就是USB设备模块用来实现MCU与主机进行数据通信的一个专门的数据缓冲区,我们称之为USB硬件缓冲区。说得具体点就是USB模块把来自主机的数据接收进来后先放到PMA,然后再被拷贝到用户数据缓存区;或者MCU要发送到主机的数据,先从用户数据缓存区拷贝**MA,再通过USB模块负责发送给主机。
    5 i# l( _4 g. z# m/ P  z
; @: M0 |0 S2 j+ \9 ?0 E

, G% {1 ?. B5 o3.4.2 5个CDC的PMA怎么配置?
  • 啥也不说,先上代码/ X5 E& A7 y1 Q2 e: _

: A8 A# S4 h# C- P: o; o- d9 w
8 K( g7 C  a  h' u3 b6 L# M  K/ B* B
  1. u_int16_t ep_addR=0x70; //起始分配地址: 这里是大坑 casojie- @. w$ ~9 m% ?3 e
  2. u_int8_t ep_addr_size=64;6 d( c4 c* m& e. k$ n) s. t! _' e* F2 ^6 N
  3. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;   //此端点是用于USB枚举和基本的通信使用,默认就有,且不可省去
    9 t" s! n, S3 k1 p3 g
  4. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
    " S- n$ l2 ^; [( C0 D2 Q( f1 S6 K
  5. /* USER CODE END EndPoint_Configuration */
    4 \4 B7 [. D! m9 C& d
  6. //CDC0 每个端点都分配了64B- W9 a( p, N1 b7 }( Z0 v
  7. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;+ t5 c) p; V' N8 m* U
  8. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;: ^9 ]& v7 X+ J. O

  9. ' e+ I3 ?" L% s" m- o4 k& x( R
  10. //CDC1                                                                                                //+5# w7 c- X+ \9 N  {: z( z
  11. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP1, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  //192 258+ r  W5 v/ D0 _+ ?0 r" |7 o
  12. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP1 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;    //272 2A8
    4 ~" A; C, p# x, t9 L: L# q
  13. . F7 g5 }/ k7 X: |- n
  14. //CDC2$ E3 |5 W2 {( C' I3 [7 |
  15. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP2 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size; //0x270  ~5 x- ]' w8 ~. p+ s
  16. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP2 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;//0x2C09 s8 ?" K; b& _% L$ e
  17. 8 M/ k( j$ Q/ t4 a* e- ?
  18. //CDC3
    + z$ u# K. I3 ]5 \8 ?% X
  19. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP3, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  //192 258 0x1E0& H; ], y6 C9 A! F
  20. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP3 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;& {* V( z+ L& o: v

  21. : g4 f9 q& k* P( c1 F& ], E+ m, v
  22. //CDC4& J* @- |2 O, J- [" s1 V
  23. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP4, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  
    4 m, u2 G. ~; |8 U3 _: O  b
  24. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP4 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
复制代码

; ^* }' X+ }0 v7 H& [2 p9 L8 t. X2 C2 [+ `. v$ ~
  • PMA图(我理解的)  |9 u7 w1 w7 {/ z: F2 S
- I- S3 R8 V5 i* A6 v- e" _2 l+ i
  • 在PMA的开头部分,是用于记录信息的,这些信息就是:端点缓存区的起始地址:说这简单点,里面写了端点0的缓存区的起始地址是X,端点1的缓冲区起始地址是Y等等
  • 由此可见,当使用的端点数量比较多时,信息记录区索要的空间就比较大,反之,就小,需要动态调整
  • 由大佬的帖子可知,记录一个端点的起始地址信息需要8字节,那么我们五个CDC,则5x2(IN,OUT)=10,再加上0x80 ,0x00端点,一共12个.则12*8=76字节
  • 因此,端点(0x00)分配的地址需要往后偏移,默认的不行,如这次需要76字节的大小,换成16进制,0x4C,我设置了0x70>0x4C,默认的太小了,会导致部分信息记录区被端点0的数据覆盖,而导致部分端点无法使用.
    / Y# C- l* e% P7 ]# A2 T

2 R" q+ G% @2 J2 ?4 Z
: e; b* l. [3 j' i3 f( }5 m6 _% E
4.修改USB初始化代码,新增对新端点的初始化; Z9 W4 [0 q9 ^

1 I0 g7 y7 r7 v4 ~$ p
  1. static uint8_t  USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)3 v& ^* c9 N7 `8 b' j3 D
  2. {7 R! M* J8 [9 M0 r9 o7 p) i
  3.   uint8_t ret = 0U;. u1 h" A0 P/ }) y  d5 d9 |9 y
  4.   USBD_CDC_HandleTypeDef   *hcdc;8 z+ ~7 Y' y" p; t4 N8 e" R) r
  5. 8 X* _: b, q' }2 ?& a) S
  6.   if (pdev->dev_speed == USBD_SPEED_HIGH)
    # {7 ?  l, u# u( m* S; k, @
  7.   {* \6 W- }3 Q4 n2 c8 A
  8.     /* Open EP IN */
    , h. f3 \- u" U' e# W# }
  9.     USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
    % i2 d% u2 q# \0 |+ F, }
  10.                    CDC_DATA_HS_IN_PACKET_SIZE);
    1 A% _. W* k/ l) t

  11. ) C4 `+ `8 v! K3 P
  12.     pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
    ! Q" O. U& a; {2 e
  13. ! G# T3 Q# l5 F6 `# F6 K7 W2 h3 t  O
  14.     /* Open EP OUT */2 b; ~: G8 J7 u0 X  ^- N: s
  15.     USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,* e! V" T+ g4 U' O  v
  16.                    CDC_DATA_HS_OUT_PACKET_SIZE);$ h: r: _7 u3 S& J
  17. ) ^5 j" ]# M2 K# c1 N+ Z  v
  18.     pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;' M& K3 ?  G8 k, K# k1 q" G
  19. * C. A- n& _+ z0 _8 k- M% W- O
  20.   }1 P. T4 Z2 ], |# O: }
  21.   else
    3 w& V; d) `6 N" a/ n. \
  22.   {$ i9 e, ?( U0 b0 Q
  23.     /* Open EP IN */
    1 ^  t" {6 ^& U/ W$ {, C
  24.      USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,/ K; W. n0 b& N' |" p! `
  25.                    CDC_DATA_FS_IN_PACKET_SIZE);
    2 s) U( ]% u+ ~2 ]
  26. " x& {4 w" ?/ b3 `& E
  27.      pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;7 \! E# M: s4 a# U4 V6 _

  28. 4 i  _" F2 b" f& d3 q+ u' t! B" l
  29.     /* Open EP OUT */
    & o6 K+ }5 w$ J' z, e. k
  30.      USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,9 w2 I7 r& r8 R% {( M3 w
  31.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    , o$ B% t7 B1 h

  32. 9 B$ X7 m- Z% ~' c: d
  33.      pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;' S1 ~5 f2 e- j* e; ^( \
  34.   {3 y3 d+ A9 G6 z2 Z: Q9 C

  35. " A$ `4 l# v$ i/ ?; N  o5 G
  36.         /* Open EP IN */
    . H) a7 k" x3 m" C$ v
  37.      USBD_LL_OpenEP(pdev, CDC_IN_EP1, USBD_EP_TYPE_BULK,. L: I: T5 g* M( G+ N$ W
  38.                    CDC_DATA_FS_IN_PACKET_SIZE);
    4 `+ ]) X1 N! c" z9 x
  39. : U: a5 v7 |# G. k0 x% U3 L
  40.      pdev->ep_in[CDC_IN_EP1 & 0xFU].is_used = 1U;
    ) P! N6 n" u  u% ^

  41. ( O, @# T) T$ T8 |$ a$ k5 s
  42.     /* Open EP OUT */* P' o: m' i4 z
  43.      USBD_LL_OpenEP(pdev, CDC_OUT_EP1, USBD_EP_TYPE_BULK,5 S/ l2 Z" m& Y. H% O/ v
  44.                    CDC_DATA_FS_OUT_PACKET_SIZE);6 x: ^0 d* b0 c0 v- R: F& ^) `, a
  45. 3 f; Y& \) Y9 F: r$ M/ a6 Z: @8 e
  46.      pdev->ep_out[CDC_OUT_EP1 & 0xFU].is_used = 1U;# Z6 a: h( |: F' y3 Z

  47. ! g8 [- U3 ?9 ~9 B0 z7 k' F

  48. 4 |6 b, J  L2 [) _- Z
  49.   E7 j8 t1 T4 P
  50. //--------------------------------------------------------------------
    $ [, ~2 i& d# U, `
  51.        /* Open EP IN */
    & R6 e! l  z- `$ v
  52.      USBD_LL_OpenEP(pdev, CDC_IN_EP2, USBD_EP_TYPE_BULK,
    + h! w$ I! Z8 n) h* I* G" d# b9 y
  53.                    CDC_DATA_FS_IN_PACKET_SIZE);
    ! C6 j. e4 q1 c% }' m$ ?7 J# s: l8 b
  54. 4 f  z/ _; s' m0 P% a: j0 b
  55.     pdev->ep_in[CDC_IN_EP2 & 0xFU].is_used = 1U;, s* D3 S  G8 V: q2 ^8 d

  56. 5 S5 M9 }6 m! ~# w% W
  57.     /* Open EP OUT */* O+ d* j9 g! v, T- @
  58.     USBD_LL_OpenEP(pdev, CDC_OUT_EP2, USBD_EP_TYPE_BULK,) q4 X3 d* S+ }8 G5 [
  59.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    9 M; H9 a) R& e3 X( Q& ^, a1 |% c
  60. # |4 \% Z9 k, M1 O! C: X3 {
  61.     pdev->ep_out[CDC_OUT_EP2 & 0xFU].is_used = 1U;
    9 f) V. p1 ^$ Q
  62. + {1 w1 R+ }; Y: r& J. O  }
  63. - j8 z( N* `- P/ A( ~+ g
  64.    //-------------------------5---------------------
    % O! W9 c5 q' s) J' C
  65.            /* Open EP IN */# z: y- J# }7 T% ~
  66.     USBD_LL_OpenEP(pdev, CDC_IN_EP3, USBD_EP_TYPE_BULK,
    ; z$ C8 ^7 x" l2 F/ x
  67.                    CDC_DATA_FS_IN_PACKET_SIZE);
    + t5 J3 ~) g2 q( {1 n5 g' F
  68. + n3 K! d( K6 x# m& V# H# L  P0 M
  69.     pdev->ep_in[CDC_IN_EP3 & 0xFU].is_used = 1U;/ p9 ^* Q' r' A$ W3 y

  70. 7 a; |. l3 }" i& U8 I) g
  71.     /* Open EP OUT */
    ! V7 B* d6 k5 c5 r2 w/ i
  72.     USBD_LL_OpenEP(pdev, CDC_OUT_EP3, USBD_EP_TYPE_BULK,5 {  Q' n5 \/ \! u1 ~+ \4 ]( ~
  73.                    CDC_DATA_FS_OUT_PACKET_SIZE);5 w" |( V) I8 {, L/ O7 l4 j  x
  74. 8 Y! u# [/ ^! T7 e
  75.     pdev->ep_out[CDC_OUT_EP3 & 0xFU].is_used = 1U;
    7 w: b. N$ P. q

  76. 5 y) n) u0 {4 G# g- r
  77.     //-------------------------5---------------------
    , K) i/ P) _" y" }

  78. ' V" J+ L$ ]( W3 h
  79.            /* Open EP IN */0 y3 Y1 H0 f+ l  A' W
  80.     USBD_LL_OpenEP(pdev, CDC_IN_EP4, USBD_EP_TYPE_BULK,) U2 K0 P/ K8 b: \% V
  81.                    CDC_DATA_FS_IN_PACKET_SIZE);% s1 S- ]0 c) O/ D% l/ j; b0 B, P
  82. " X' b4 I: {' L0 F0 b
  83.     pdev->ep_in[CDC_IN_EP4 & 0xFU].is_used = 1U;
    ) X# v  D8 S& I; d; A) X
  84. & e+ x$ Y3 S3 C6 W
  85.     /* Open EP OUT */
    3 E+ Q3 W& S) s/ B
  86.     USBD_LL_OpenEP(pdev, CDC_OUT_EP4, USBD_EP_TYPE_BULK,* J3 s2 _: S/ c1 `+ ?3 F2 ~; W; ^
  87.                    CDC_DATA_FS_OUT_PACKET_SIZE);; p& J& Z9 P, C

  88. ; R" \4 O5 P1 X8 Q
  89.     pdev->ep_out[CDC_OUT_EP4 & 0xFU].is_used = 1U;  v0 E" a9 @- |' j3 M8 n) z* W! ?/ i

  90. 2 q9 B% ~/ Y" M+ J
  91.   }0 A" \- c2 c$ |5 f% K1 o: s" x
  92.   /* Open Command IN EP *///控制端口无效,不要取消注释' X' Z( \' C1 s
  93. //  USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
      f- T* J1 D1 v: S
  94. //  pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;
      V, E/ |$ y5 ^* N2 r' ~: y9 b: ]
  95. 9 X7 c1 R- `/ N
  96. / k4 v3 U/ l7 M. X
  97. //   USBD_LL_OpenEP(pdev, CDC_CMD_EP1, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
    % `8 r* l+ m) N( C
  98. //   pdev->ep_in[CDC_CMD_EP1 & 0xFU].is_used = 1U;
    9 ~' L: c: B- C- e

  99. ) Q8 t& ^  Y3 Y5 P8 h  r9 j: _

  100. 2 v' y1 s) }! p: `! s; @9 L  v: H7 G
  101. //     USBD_LL_OpenEP(pdev, CDC_CMD_EP2, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);+ U! ?$ @7 W* Y; k& G
  102. //   pdev->ep_in[CDC_CMD_EP2 & 0xFU].is_used = 1U;
    ! x4 Z. r& r- I

  103. 1 @4 ~  k) }/ u, h! K" ]' ?
  104. - b1 j# R9 m! J( H; h( n
  105.   //   USBD_LL_OpenEP(pdev, CDC_CMD_EP3, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
    % j; M9 M" S4 x6 @! u/ _+ y2 ^
  106.   // pdev->ep_in[CDC_CMD_EP3 & 0xFU].is_used = 1U;) W3 o8 T1 y0 r& s0 l
  107. , r1 f9 B0 B' N& f. z2 N
  108.   pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));0 A( F* P: Z" [: Q: {6 {/ j) ^0 U
  109. 1 A4 S# j4 ]4 Z
  110.   if (pdev->pClassData == NULL)
    7 Q0 _& t8 A0 ~, f/ B* D9 t* W
  111.   {
    ! n; B- l* L# [, [
  112.     ret = 1U;
    , l6 C9 U/ w& T3 Q: x
  113.   }* |0 T% {1 u- F( g: I3 d: g; M2 C9 G
  114.   else
    , l. @2 I& d, u
  115.   {
    9 J  B; C; W( y/ N
  116.     hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;3 @* h1 \9 _; J4 |3 L
  117. & ^. \7 [; r; M. o( `+ z
  118.     /* Init  physical Interface components */
    # Z9 M/ m- a6 @) c8 v
  119.     ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
    + b0 y* p2 ^" E" w3 N2 V: ?( W
  120. 7 W" T- I$ e" p9 _, c6 b& w6 ?
  121.     /* Init Xfer states */
    + W& h- W% k$ x. [' c0 W
  122.     hcdc->TxState = 0U;
    7 E' e6 ?9 Q4 Q8 U, G( o1 q; p- a
  123.     hcdc->RxState = 0U;7 C" U9 x5 H! e8 O8 \4 x0 A# v
  124. 5 ~8 W3 [5 e# n) w/ V4 ?' `! @
  125.     if (pdev->dev_speed == USBD_SPEED_HIGH)
    9 A$ b3 G. g- P8 {4 P2 h8 n% I
  126.     {3 Y* B1 k0 Q$ Z% N. C. J- I
  127.       /* Prepare Out endpoint to receive next packet */5 @. t! y. v) ]! b, s1 o
  128.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,2 e4 H& T4 F. {* c2 |
  129.                              CDC_DATA_HS_OUT_PACKET_SIZE);
    & Z9 i# I' j  ?* U. w
  130.     }% S/ i' m. f% j
  131.     else
    + k4 J$ M* ~% J. v% G. F  Y* l
  132.     {; R3 g$ U/ n8 x
  133.       /* Prepare Out endpoint to receive next packet */6 J# {/ S( ^. A4 L  c3 n5 A' L4 c
  134.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
    , ?; \( K; [9 n' h" D9 X2 t/ F' R
  135.                              CDC_DATA_FS_OUT_PACKET_SIZE);; D9 d" N  A1 E" X
  136. : H6 J' z8 P  E
  137.                                    /* Prepare Out endpoint to receive next packet */
    ) n! p- d6 `$ u3 o# A
  138.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP1, hcdc->RxBuffer,4 z( H3 k9 D7 r6 Y" f  p
  139.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    3 O& ~. z5 S  e. Q9 X

  140. 4 t4 c: `" N$ \9 U; e
  141.                                    /* Prepare Out endpoint to receive next packet */
    / T) Y" A4 n+ R+ s8 U9 L
  142.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP2, hcdc->RxBuffer,
    ' V. I$ V+ M. e; I! e. w8 N
  143.                              CDC_DATA_FS_OUT_PACKET_SIZE);3 B. j1 f$ F% h' k9 k2 `

  144. * Q# N3 r/ O' C6 c6 t
  145.                                    /* Prepare Out endpoint to receive next packet */2 @' M  D# Q" t( U7 w5 T) }
  146.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP3, hcdc->RxBuffer,
    . M) c5 Y# G7 a8 N) [3 P
  147.                              CDC_DATA_FS_OUT_PACKET_SIZE);' |, z( f3 V) X, q4 O/ n# O. A8 @

  148. $ ^9 a& O! D8 `8 W" h7 _0 T
  149.                                                              /* Prepare Out endpoint to receive next packet */% K1 W' g* Z/ p; ]
  150.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP4, hcdc->RxBuffer,% F9 m# v$ q$ k, q6 c' K0 g, l
  151.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    3 b) d& T) w$ Y% q$ R
  152.   k7 l- a6 A4 u+ f: O' K
  153.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP5, hcdc->RxBuffer,
    % J: v) f% m+ g; l' L
  154.                             CDC_DATA_FS_OUT_PACKET_SIZE);6 d( `1 X1 ~2 ]0 i
  155.     }! _3 l6 q+ Q) |( O2 q- E. n# Y
  156.   }
    5 ]  c% x$ i, E+ h5 G
  157.   return ret;! {/ f: j1 h$ D+ A8 y
  158. }
复制代码

1 f: Q$ p2 l2 t+ j: S  R9 `# a* h6 R4 Z
0 m# m8 F! c9 `! |' L# {" K/ a5.修改HAL默认USB CDC相关接口函数
  • 现在是多CDC的状况了,但默认的HAL库的函数均只是针对一个CDC的情况,我们需要将端口的参数引出来
  • USBD_CDC_DataOut:USB接收函数回调,修改提供端口参数
  • CDC_Receive_FS(uint8_t *Buf, uint32_t *Len):USB CDC接收函数
  • CDC_Transmit_FS(uint8_t* Buf, uint16_t Len):USB CDC发送函数
  • USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
  • USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev)
    ! j; x' _5 v' i

  • 先说说这几个函数的关系:CDC_Transmit_FS---调用--->USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
  • USBD_CDC_DataOut(数据接收回调)---调用--->CDC_Receive_FS7 W# k) N6 R2 A! y

CDC_Receive_FS(uint8_t *Buf, uint32_t *Len)修改为CDC_Receive_FS(uint8_t* Buf, uint32_t *Len,uint8_t epnum): 此后所有OUT端点来的数据都将进入此函数,可通过参数epnum区分
! j! h! V8 r% d/ a8 f
  1. static uint8_t  USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)( w/ S8 i" s! U. {6 l* }( f
  2. {
    + Q- d+ @0 J' w8 J
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
    % y2 \( q: y; q. j& l1 t* K
  4. ( \7 V9 `0 [. I- I9 a* `+ x$ o9 g6 C
  5.   /* Get the received data length *// ]5 z' c/ V" w$ n
  6.   hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);4 z1 E/ k% a: {
  7.   /* USB data will be immediately processed, this allow next USB traffic being+ M- D  j% W' N8 R9 A, a
  8.   NAKed till the end of the application Xfer */
    3 ?3 Z( p: b+ g( A% c
  9.   // printf("USBD_CDC_DataOut.1294:Len:%d :EP:%02X\n",hcdc->RxLength,epnum);
      O& M) y4 q; }# m! q
  10.   if (pdev->pClassData != NULL)
    7 T# x% O  I( T) R
  11.   {! r1 W. M/ U. x* B/ i
  12.     ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength,epnum);//此处修改,加入端点,相关的函数声明也跟这这样改
    8 O0 E. d9 M$ R5 J0 v+ ~% q
  13.     return USBD_OK;
    ( r  E0 q1 T3 d; a$ r3 Q- R
  14.   }( U# `" S; ]/ W: F8 G9 V6 q" k

  15. ! O' {* a, y3 u
  16.   else6 z2 w7 A. q: }, U
  17.   {
    2 r1 ?. m$ Q& h$ t' I3 c3 w  N
  18.     return USBD_FAIL;
    # [( g7 M" _+ Y, E6 g/ C
  19.   }
    ; z3 N3 M# ^3 ]
  20. }
复制代码

4 V: W! k9 h4 k0 H# [8 p. x9 R& M
  • CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)该为CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum):只是增加一个参数,函数体不用动4 o3 L& D1 N& a( S6 z
( w% }$ r% T$ C, V% n( M  `8 {

' h9 |4 \. ?& N: F& N+ ?8 ~
  1. uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum)& q2 `  ^+ w: ~% Y  w* M
  2. {+ X6 h/ ?0 ^% X
  3.   uint8_t result = USBD_OK;
    3 P, X0 ]- `( W9 {% n, B- v
  4.   /* USER CODE BEGIN 7 */
    5 ~( y& m" ]- I3 M0 I* A
  5.   USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS_CDC.pClassData;
    - S- m% c4 w# s7 s3 e" f
  6.   if (hcdc->TxState != 0){0 Z. u% d: y$ g; Y# M7 I
  7.     return USBD_BUSY;
    9 ]8 I& c% z$ r; A+ E
  8.   }
    ) d7 P$ o6 r2 ^8 T
  9.   USBD_CDC_SetTxBuffer(&hUsbDeviceFS_CDC, Buf, Len);& j3 ~2 e/ q5 m: {) y! H
  10.   result = USBD_CDC_TransmitPacket(&hUsbDeviceFS_CDC,epnum);    //将epnum的端点传到这个函数,这个函数也需要改$ K0 y" V1 ]* Q) Q3 Y0 M& E
  11.   /* USER CODE END 7 */
    3 D6 K" @, o8 n* y0 t) b3 I
  12.   return result;8 }. x8 W' F1 I
  13. }
复制代码
0 F! a# m/ T0 z5 T+ R
  j) P% s4 I8 r8 V8 @& w- G
  • USBD_CDC_TransmitPacket的修改0 ?4 o" A8 F( F
  1. uint8_t  USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev,uint8_t epnum)0 H5 u" I# n7 I* `/ `
  2. {; `/ q5 c5 ^8 H# G, t( h6 N& A
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;; Y+ K' Y) T. s4 c2 r
  4. , j/ Q. o4 L' P6 s5 @& s
  5.   if (pdev->pClassData != NULL)
    7 d# w3 o3 y  R7 `9 c
  6.   {
    # o) t- U0 g# y) J
  7.     if (hcdc->TxState == 0U)
      ~9 c# q. B. }
  8.     {
    % t7 [1 X8 B9 |) n
  9.       /* Tx Transfer in progress */
    8 ^% g+ j$ k+ F% y, t  [! U& M
  10.       hcdc->TxState = 1U;
    $ M: K& M; I# s# d& [

  11. # M/ s  E( i3 z
  12.       /* Update the packet total length */2 D! w( x) w  [$ M  S
  13.       pdev->ep_in[epnum & 0xFU].total_length = hcdc->TxLength;//将原本的CDC_IN_EP更改为我们传入的端点
      h: X3 S( {& o9 Z- W
  14.       /* Transmit next packet */
    " I3 l- ~- \! M/ T- _- [
  15.       USBD_LL_Transmit(pdev, epnum, hcdc->TxBuffer,
    ) Y8 R& L2 Q$ i2 n. d
  16.                        (uint16_t)hcdc->TxLength);//此处也是0 _+ [5 K" _8 u; C2 H. c

  17. , P, ~  Z3 z* V
  18.       return USBD_OK;; P1 o; R; N9 L5 I/ m1 U
  19.     }2 P2 m+ s: ~: t# A6 T) T4 C7 W8 L
  20.     else: S2 L2 _# H) y3 C' @  a
  21.     {
    - Y! o' T. R3 v" F* C5 C( S
  22.       return USBD_BUSY;
    - g  n5 a2 t& x3 P
  23.     }- l  S: e% C' D( ~
  24.   }2 }3 s# k& B% {, n; e
  25.   else
    5 E! {( k" |( u( I7 e  p
  26.   {
    ! `) I0 f4 s/ D1 U
  27.     return USBD_FAIL;
    1 l8 X! M" |9 t9 b. F" v# V' N+ ?
  28.   }
    : m6 J  _" @8 w% {$ O: @
  29. }
复制代码

7 z2 N- p- X* k7 u' u( @$ k" W5 v- t1 F

该函数的作用:当端口接收一包数据后,需要执行此函数来接收下一包数据,简单的说:告诉主机我可以接收下一包数据了

" ?. m5 U, i: S. x
  1. uint8_t  USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev,uint8_t epnum)
    $ m4 C) e6 N2 J
  2. {
    5 m; e, h4 }! q! @
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
    + u* |9 j1 J! x3 r" y
  4. . M2 c. k3 {! y
  5.   /* Suspend or Resume USB Out process */
    " B) A* L1 }$ e+ c$ Q: D
  6.   if (pdev->pClassData != NULL)
    9 _( y: }% y1 q8 S( h
  7.   {
    3 C6 D$ n4 ^0 K. W, c2 D& Z
  8.     if (pdev->dev_speed == USBD_SPEED_HIGH)
    / {/ i5 |' Z. d4 o5 C
  9.     {
    * {% t* `$ B* _8 X* w, k
  10.       /* Prepare Out endpoint to receive next packet */
    + {! Y& J' |1 p; Y! g" F8 X
  11.       USBD_LL_PrepareReceive(pdev,
    0 o) N' y, x) h9 Z" W3 E7 V! Z, ?
  12.                              CDC_OUT_EP,
    9 e6 c% s7 M2 g. O* a3 C! ~
  13.                              hcdc->RxBuffer,
    6 s7 ]2 C& @3 h3 a7 c
  14.                              CDC_DATA_HS_OUT_PACKET_SIZE);
    5 `/ H: ]5 x2 O5 [2 d; O; h
  15.     }
    6 r* S; C) j: O* z6 m& d0 K
  16.     else$ S/ g) g5 {% f6 `! F0 ^7 D
  17.     {0 M& Y( @5 ]0 L4 I7 E$ J' ^" b: t
  18.       /* Prepare Out endpoint to receive next packet */
    & w: I3 v! o) h! j/ ^
  19.       USBD_LL_PrepareReceive(pdev,9 w7 a) u& z7 Y" j) R
  20.                              epnum,
    0 [$ n$ O* z: G7 ?) E. M7 G" J' _
  21.                              hcdc->RxBuffer,! O. e$ U' B, o
  22.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    % ]  L! u, O/ {# F$ t2 |+ i1 l
  23.     }
    ( B- a# M( X# r8 M% N; j/ s
  24.     return USBD_OK;
    $ R/ w5 y# ^% G! t3 a
  25.   }
    1 p8 O, W' D; Z% V% A7 Z4 u" c
  26.   else; A; }$ o& |7 `! u) C5 s; V7 l) ?
  27.   {
    + b* Z; U4 F% V3 x+ f) ^$ L
  28.     return USBD_FAIL;4 v! C( p  k0 Z4 L
  29.   }
      N; V6 \: T; c& u
  30. }
复制代码

/ t0 l. D, _8 A) W) H
对以后而言,我们就使用CDC_Receive_FS(uint8_t* Buf, uint32_t *Len,uint8_t epnum)和CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum) 向CDCx发送数据,就填写CDCx的IN端口 * 接收CDCx数据时,CDC_Receive_FS函数会传入该数据来源(OUT)端口,就可知道哪个CDCx了
7 U: {7 `. q; S) W. [, K. F4 k
6.后续
  • 此时就完成了,不过不排除有些深层的问题。
  • 如:当五个CDC同时在Read时,其中一个close,有可能会导致其他四个都无法再Read出数据,需要重新Open,但在电脑的深度depin系统上并没有这个问题,在项目中的板子上就有,希望大佬们提供下线索。感激不尽
    . t+ a$ E/ u, _
8 K8 i) q, N8 M2 a# i7 d. H( d; M
: g# z  ^3 q, z" s% ?
转载自:casojie/ H; X5 _; B) s, n
收藏 评论0 发布时间:2023-1-3 19:55

举报

0个回答

所属标签

相似分享

官网相关资源

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