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

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

[复制链接]
STMCU小助手 发布时间:2023-1-3 19:55
1. 背景
  • 由于项需求,在STM32F072中需实现5个CDC设备,折腾了很久分享出来,希望能帮助别人少踩一些坑.USB2.0全速,该款单片机支持8个输出和8个输入端点
  • 4 c, q* ?; [. A* Y/ y$ W2 R
2.1 它是什么?需要使用到什么?
  • 它是USB设备类型的一种,如U盘插入电脑时,电脑会知道其是U盘,是一个存储设备,那么它就属于USB MCU存储设备。USB协议中对设备进行了分类.它在stm32上叫虚拟串口设备,当将其链接电脑后,可以把它当成串口使用,如使用windows的串口工具打开它,设置波特率等等,这是我的理解。
    8 d# v& [7 }) S- ?
- D2 m# Z1 B+ W1 f8 h4 P
  • 它需要两个接口,三个端点* d4 C4 A3 p1 }
1 k0 Q+ @- N* D9 s% D$ S! w
  • 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都是相对于主机而言
    + f. c" M( E  \& `2 t4 I
  • 由此可见,正常情况下,一个CDC需要三个端点,其中两个IN端点,一个OUT端点0 `; k% C: B+ i- f
    - I: z7 j" @( V4 z/ G
3.配置过程3.1 配置流程
  • 在STM32CubeIDE的帮助下,生成一个CDC的代码,这里没什么坑,点几下就成功了,注意的是可能需要将Heap设置大一点
  • 修改设备描述符
  • 分配端点和修改配置描述符
  • 分配PMA端点缓存地址
  • 修改HAL库关于CDC部分函数接口的参数,以适配多CDC设备的情况
    2 x/ x6 H( |: I; O) X" W5 P( H
# L4 u+ `6 y! N/ e

9 L0 t; s* q7 ?1 A% l& F0 |3.2 使用STM32CubeIDE生成一个CDC程序的代码
  • 根据下面的文件操作即可,文件会介绍USBCDC的知识,在PDF的最后会说怎么使用cubeIDE配置,很简单没什么坑(注意的是可能需要将Heap设置大一点)8 F' P6 |2 _/ a4 T9 B
8 ]% u9 j/ T" E; X3 q

: O8 a. T+ l1 H$ p  G3.3 分配端点和修改配置描述符
  • 此时问题来了,CDC要求3个端点,其中2个输入1个输出,而stm32F072只支持8个输入端点,8个输出端点,2x5>8,正常情况下是不够的,这里就需要将IN端口中的控制端口省略,也就是第一幅图中的Interface 0中的endpoint IN端点,不分配有效端点给它,在本款单片机中IN端点的有效范围(0x80-0x87),OUT(0x00-0x08)
    5 x' I8 L' E' i4 |  \; n

! ^# ?9 t+ }& i6 D7 s$ ?

& }/ N% G, c$ e* Z( L
  1. #define CDC_IN_EP                                   0x81U  /* CDC*/
    - p+ v) f$ x1 I
  2. #define CDC_OUT_EP                                  0x01U  
    3 W4 D/ i' T; P* Q! r; R
  3. #define CDC_CMD_EP                                  0x88U  //无效端点
    7 r1 B. }! p, A8 y$ s
  4. 5 f9 V! F' @5 ^0 e0 ~* W
  5. #define CDC_IN_EP1                                   0x82U   /* CDC1*/
    . W, F  P+ G3 {: l2 k8 W
  6. #define CDC_OUT_EP1                                  0x02U  $ K) o0 ?( l4 Q( A' B1 L# R# L
  7. #define CDC_CMD_EP1                                  0x89U  //无效端点
    8 N, C. ~& g* W
  8. 4 \3 W: R3 O5 v: C4 s
  9. #define CDC_IN_EP2                                   0x83U   /* CDC2*/
      g; o0 b2 X/ s
  10. #define CDC_OUT_EP2                                  0x03U  : `0 _8 \, i0 O; J
  11. #define CDC_CMD_EP2                                  0x8AU  //无效端点
    7 O/ O! D' b4 [; k+ o" Y5 H6 M
  12. 7 b5 c7 `" b8 _2 n1 o2 a: S
  13. #define CDC_IN_EP3                                   0x84U   /* CDC3*/
    . a. F8 \: d2 u7 C2 Q
  14. #define CDC_OUT_EP3                                  0x04U  # r' B8 ~4 R7 u6 [$ U( W( D# |
  15. #define CDC_CMD_EP3                                  0x8CU  //无效端点
    . [$ x* \4 P0 |: t& B( w8 M' T

  16. ' G% X; g5 `4 b
  17. #define CDC_IN_EP4                                   0x85U   /* CDC4*/
    ) ?, c5 A4 }8 j
  18. #define CDC_OUT_EP4                                  0x05U2 D5 C# s5 J1 Y/ _8 Q: i
  19. #define CDC_CMD_EP4                                  0x8BU  //无效端点
复制代码

: ^! E5 i7 ]! I  ?, m4 r# v
, V! n5 b7 ~. G" K0 c$ n& ~
  • 修改配置描述符号,这里面的内容就很多了,里面涉及到USB方方面面的属性和参数,其中USB_CDC_CONFIG_DESC_SIZ是该结构体的大小,记得修改,或者直接改为最大255。
    $ I* i: p1 h% V
  • 配置描述符的结构如下:
    # t; U8 K  T8 E, _! F

    ( O' H4 m8 \, h7 E6 C
  1. 配置描述符
    7 q. J/ i/ u7 q" s
  2. {
    ( j5 s2 T3 {+ {( \% F0 j6 j
  3.     配置描述符总概括(相当于预览:9字节)+ l" ^5 u0 F! o' H4 w3 O
  4.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC* m9 S0 L7 r: E! f2 V
  5.     {* `2 w4 r- _% P, m7 a0 p
  6.         接口描述符1
    3 L; X( @- P$ R; f3 K
  7.         {
    ( V, G. V  z* y9 K- z+ j' E# _3 E
  8.             其他描述符(ACM等)! D8 [1 [) z9 r/ C; T, t, h
  9.             端点描述符(控制端点)
    , g" [/ O/ I7 `  T
  10.         }0 T; r) u# [/ {: X5 v
  11.         接口描述符2
    # d. o" v  i1 v% ]% M+ \, a6 E' D
  12.         {, P2 Y' j9 c/ G+ K5 I
  13.             端点描述符(IN)
    / s5 w, E7 `( j4 U
  14.             端点描述符(OUT)
    4 f( n! @/ c3 H- x6 u6 A
  15.         }) N# l5 p! l5 ^& G5 b: u2 l
  16.     }
    ) A. T. k( y* D6 x$ @

  17. * p9 v" r+ R  Q
  18.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC1% u* A+ a! K$ C* X0 A5 j
  19.     {: b4 @6 I$ a; }; Q! d/ J7 i& _3 ?8 y
  20.         接口描述符1! N$ v; w# A; {5 s( V: I
  21.         {& [* h2 s& g4 R) D' v
  22.             其他描述符(ACM等). J, }6 x& r7 i) }7 x' C' E% g
  23.             端点描述符(控制端点)$ I! I. q: a) _5 F  X) _. l) K, \, O
  24.         }  K$ f; n! M' e& B( u
  25.         接口描述符2
    # E* D3 L, @1 f+ {
  26.         {/ b, u& w& i. f. ^
  27.             端点描述符(IN)
    8 y0 m6 ?2 M: {: n3 s
  28.             端点描述符(OUT)5 L% U4 r1 o7 C, b; y/ q
  29.         }
    " B. n) w4 S0 ~
  30.     }, Q' G" [4 X+ A7 _

  31. / `: ^& R; Q$ h
  32.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC2
    . Q* f7 R+ d- J4 H; c: N# K
  33.     {
    5 I# J; y, e$ n0 m% b0 a
  34.         接口描述符1
    ' h, d9 J8 {; h
  35.         {
    + v7 L$ k% D0 ]9 ~* x; Q5 t! T) b
  36.             其他描述符(ACM等)
    # f3 }( K% @) P4 H
  37.             端点描述符(控制端点)$ m( `3 H3 A, N) y- z+ o
  38.         }1 @( M2 B6 O9 U5 B* z
  39.         接口描述符2/ b3 n& C: u5 ?. X' m! X" e
  40.         {% A4 x) n: o1 _; l
  41.             端点描述符(IN)
    : n: T" v1 {6 k
  42.             端点描述符(OUT)
    0 V7 z5 R+ v: b- [* R
  43.         }' Z+ v9 N. A& a
  44.     }
    2 A+ j& z9 v8 ~! Z

  45. 7 v) c: w  Z, b) B6 L$ n
  46.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC3
    4 J- O3 K0 d; E& ~' M- e: ~
  47.     {" ?2 r+ k, _# D; {7 S
  48.         接口描述符1
    , t0 g6 T& q6 t$ P# P
  49.         {* B/ J6 ~8 q% S( s3 K' A8 Q" }; v
  50.             其他描述符(ACM等)* e2 @- B! C+ `5 m% W0 Z
  51.             端点描述符(控制端点)
    % w( y2 ~. T( z9 o1 i
  52.         }4 n8 q: T& I& Q7 W9 y' ?
  53.         接口描述符2& j8 {* I8 w% K" |& B2 Y. r, P- B1 h, t
  54.         {  ~3 Y* Z* L5 \
  55.             端点描述符(IN)
    ; U, y$ t2 w8 _1 V
  56.             端点描述符(OUT)
    7 y; ?2 c2 d% H% x' d' m
  57.         }# e/ n6 J  r* P  c$ J! t/ e+ e
  58.     }
    6 _1 ^* J7 R( c% y8 V( y8 r
  59. - Q; p, A5 w7 Y  E& U8 \
  60.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC4
    : _6 o4 p( l6 Z
  61.     {
    ) E. S! f+ S9 U
  62.         接口描述符1
    8 N. k/ r$ Q4 o- x& V  j
  63.         {
    . q5 c) ?! j  m. O/ J
  64.             其他描述符(ACM等)4 A% z1 k7 w- U0 B
  65.             端点描述符(控制端点)2 n  T6 t: s3 ]) ^- \. V8 Y
  66.         }' }+ i1 M/ d- m
  67.         接口描述符2
    & `8 s6 K1 ?$ R  \+ g" {% ?
  68.         {
    $ A+ p6 L. H7 ]0 J# l+ L! g
  69.             端点描述符(IN)  i1 }4 c* Y% f& P9 `
  70.             端点描述符(OUT)
    ' ^3 u$ ~, _5 J4 }$ t9 Y8 n
  71.         }/ _, \  P7 d3 ~2 G6 H1 F  d) J# r, U! P
  72.     }
    3 R; Y6 \9 v; o8 V. f" D
  73. }
复制代码
2 N4 R0 `& @! _% @" G
  • 配置描述符如下,下面有些字段需要修改的,都用casojie标记了,CTRL+F搜索casojie就可以方便显示;
    7 B/ F- K. ^$ N( i5 j2 n
5 S" s! ?, U+ I. Z

$ h2 P& @; d+ r0 K
  1. __ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
    6 `8 `' t/ \5 n- E0 R) e
  2. {8 L' n% o  Z5 w+ s1 I
  3.   /*Configuration Descriptor*/
    7 w/ [2 [/ J: a6 B2 j
  4.   0x09,   /* bLength: Configuration Descriptor size */
    * `2 w% V9 v0 f  u" k1 H$ l- s
  5.   USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration */
    6 Z4 E$ Y; T  v
  6.   USB_CDC_CONFIG_DESC_SIZ,                /* wTotalLength:no of returned bytes */
    2 o2 Q& L) K2 @! ~6 Q( {3 T
  7.   0x00,$ p- k% q# {! u4 z! f3 b
  8.   0x0A,   /* bNumInterfaces: 10 interface *///总接口大小,5个CDC*2=10=0x0A casojie" H0 C! l% h6 H- L( P  K  R( O; |
  9.   0x01,   /* bConfigurationValue: Configuration value */' h7 _' Z& j/ _) T! S6 h
  10.   0x00,   /* iConfiguration: Index of string descriptor describing the configuration */" R" s3 X/ S/ ]2 r# H" a5 T0 n
  11.   0xC0,   /* bmAttributes: self powered */
    3 A; O; y, D- ^# F3 H; J
  12.   0x32,   /* MaxPower 0 mA */" g% A! Q% t" b- i  ~) j

  13. 7 _' n' R  [$ P& ^
  14.   /*------------------------CDC0--------------------------------------------------8+9+5+5+7+9+7+7-*/
    * K) Y4 m  Z: [7 Z
  15.   // // // IAD  Interface Association Descriptor //IAD描述符需要添加 casojie. j" z: Q  _2 o! Y2 N# x9 |0 i2 G
  16.   // 0x08,  // bLength: Interface Descriptor size //标识IAD描述符的长度,基本都是8,casojie
    * _5 X% E# D  N% N
  17.   // 0x0B,      // bDescriptorType: IAD            //不用管
    ; e5 D9 `) W* E2 E3 v+ N
  18.   // 0x00,  // bFirstInterface                      //第一个接口的序号
    " w8 U  L' o) O2 _$ D; \! D& q
  19.   // 0x02,  // bInterfaceCount                      //本IDA的接口数量
    2 J4 `: C  u9 o2 ]( R# n6 v
  20.   // 0x02,  // bFunctionClass: CDC                  //表明该IAD是一个CDC设备
    % ^' t: a) M1 \1 Z0 S7 z1 T
  21.   // 0x02,  // bFunctionSubClass                    //不用管8 X7 V5 @! T- V
  22.   // 0x01,  // bFunctionProtocol                    //控制协议等其他我也不懂,默认就行
    , H) k0 T4 @! t8 g8 ~
  23.   // 0x02,  // iFunction   
    5 d  r- t  f" Z: m

  24. 0 S" P( u, Z" p1 s& h/ N9 }" O
  25. /*Interface Descriptor */! A! W! U. J- x* B$ |+ q7 Z4 k
  26.   0x09,   /* bLength: Interface Descriptor size */
    1 |4 h8 A& P/ X3 v; q& m" Q
  27.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    0 [( _9 X% u: U6 P& W1 Z
  28.   /* Interface descriptor type */
    ) w+ j; G+ u0 I5 G
  29.   0x00,   /* bInterfaceNumber: Number of Interface */   //接口编号,从0开始 casojie) A8 M; s6 I- c% v5 v
  30.   0x00,   /* bAlternateSetting: Alternate setting */
    $ p$ k, k8 m; i8 R
  31.   0x01,   /* bNumEndpoints: One endpoints used */       //接口内有多少个端点被使用 1个 casojie! c1 L6 b7 ]2 r$ Y# b* f
  32.   0x02,   /* bInterfaceClass: Communication Interface Class */9 `" Y3 j. a* {# \6 s; b& F
  33.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    3 e9 d. T3 i- C8 l) |
  34.   0x01,   /* bInterfaceProtocol: Common AT commands */
    ; g7 @: ~# J7 ^8 u4 U0 _
  35.   0x00,   /* iInterface: */. r, G5 F5 O8 ]& i/ U( k

  36. 0 q  I: r0 I8 ?# l  x+ G& T
  37.   // /*Header Functional Descriptor*/4 b1 C& N# w1 {  }2 X' p
  38.   // 0x05,   /* bLength: Endpoint Descriptor size */" ?4 l- u; U3 L
  39.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
      N& U: L' k- h9 |" B( s6 d
  40.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */2 C, e6 x9 ~+ ^8 Q% A! a
  41.   // 0x10,   /* bcdCDC: spec release number */
    6 m6 [7 `0 ^/ Q8 {# _  b* g3 l/ h
  42.   // 0x01,
    0 |" P/ j4 W# |. \$ ~% I. y
  43. % n; w" e7 N2 q. l( d- {
  44.   // /*Call Management Functional Descriptor*/
    8 U( z) S: c) U
  45.   // 0x05,   /* bFunctionLength */1 K- m$ ^# i; }9 T
  46.   // 0x24,   /* bDescriptorType: CS_INTERFACE */) a* @+ I5 P6 n0 o1 O
  47.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */8 ^: u" [' M% P9 t. r: X
  48.   // 0x00,   /* bmCapabilities: D0+D1 */" C- H! Z, h0 M9 d8 Y
  49.   // 0x01,   /* bDataInterface: 1 */
    8 {, |  `6 _& i+ m
  50. 5 Z1 K, k: g- k1 [" F
  51.   /*ACM Functional Descriptor*/
    ! M: c8 J) B0 v, M) K( M: z: Y1 K+ h
  52.   0x04,   /* bFunctionLength */1 @+ n/ @4 ^# V3 C3 B6 A$ Q- G
  53.   0x24,   /* bDescriptorType: CS_INTERFACE */3 O6 Z7 Y4 `. B4 S- D
  54.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    ' L; g+ A3 ?- A' I
  55.   0x0F,   /* bmCapabilities */' _, u) `) Z5 r$ [
  56. ! {& T4 n8 Y/ U8 \! i, p3 `
  57.   /*Union Functional Descriptor*/
      C7 q4 C, x' z5 Y
  58.   0x05,   /* bFunctionLength */8 O, e2 A/ O& j- _  h: m( W0 `5 U% d
  59.   0x24,   /* bDescriptorType: CS_INTERFACE */( k! x" N% L8 g# C
  60.   0x06,   /* bDescriptorSubtype: Union func desc */
    ) J7 r* J. ?9 E. Z7 c
  61.   0x00,   /* bMasterInterface: Communication class interface */ //联合描述符,与IAD功能类似,标识哪两个接口是属于一个设备的casojie6 d* U) S, H" ?; E3 d' y: F
  62.   0x01,   /* bSlaveInterface0: Data Class Interface */  //与上面一样,上面是0,这里是1,标识0号,1号接口是属于一个CDC设备的 casojie  r" t# B$ g. T) Z1 B4 u

  63. : Z/ s+ \" z% \' D# i4 B" E
  64.   /*Endpoint 2 Descriptor*/3 e, Q) r+ e; W! W6 o# V: X; h
  65.   0x07,                           /* bLength: Endpoint Descriptor size *///控制端点描述符,虽然端点号是无效的,但是这个描述符不可省略
    3 v8 B# }, }! `2 f6 {* f5 t! k
  66.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    + n% C/ `2 c$ j$ X9 g  o( Z' e6 y
  67.   CDC_CMD_EP,                     /* bEndpointAddress */
    , R, p1 A& b% J. h3 }
  68.   0x03,                           /* bmAttributes: Interrupt */
    3 J$ j6 i5 o8 d) S6 d, y" o% ~
  69.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    9 g$ s: @; t. s- V
  70.   HIBYTE(CDC_CMD_PACKET_SIZE),
    8 E6 |- q/ E" Z
  71.   0x10,                           /* bInterval: */ 9 E$ l4 N* e% S$ X
  72.   /*---------------------------------------------------------------------------*/
    ; k4 ?) ^! j+ G5 ?
  73. / p0 E- O1 a! O: [% h
  74.   /*Data class interface descriptor*/   //第二个接口描述符 casojie9 f- N! A5 U2 h# s  u  W
  75.   0x09,   /* bLength: Endpoint Descriptor size */3 k- [5 f3 H% n8 Q* N# G
  76.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */7 |- ^3 l7 m1 i2 M
  77.   0x01,   /* bInterfaceNumber: Number of Interface */   //接口的序号,上一个接口是0,那这里就是1 casojie
    . Q3 B' T  @; L8 u
  78.   0x00,   /* bAlternateSetting: Alternate setting */
    ( n3 _9 o# m5 @4 h/ p% i
  79.   0x02,   /* bNumEndpoints: Two endpoints used */       //标识此接口有两个端点(IN)(OUT) casojie- L. Y/ c& o: N
  80.   0x0A,   /* bInterfaceClass: CDC */( E+ ~' g! x, b$ V
  81.   0x00,   /* bInterfaceSubClass: */
    ( P3 v* i) _' g; |' m9 h& s
  82.   0x00,   /* bInterfaceProtocol: */$ k) @5 |1 L9 Y2 G
  83.   0x00,   /* iInterface: */
    / l+ A  z  S9 R/ G0 R
  84. ; A, s1 i$ g5 S" O8 j5 `) [
  85.   /*Endpoint OUT Descriptor*/                       //OUT端点( U0 Y6 ?( L5 ?# j
  86.   0x07,   /* bLength: Endpoint Descriptor size */
      S$ W3 j$ x; A
  87.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */; P& x: T  g  e, ]4 {3 k
  88.   CDC_OUT_EP,                        /* bEndpointAddress */
    7 E& M% \7 Q1 {, ]  j% C( d
  89.   0x02,                              /* bmAttributes: Bulk */. H' F" m+ ~; D; ]
  90.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    ' }/ r/ J+ Z* J$ ]8 w- C/ i
  91.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),$ F; Z% t! v; H& b! w% h: G- A; a
  92.   0x00,                              /* bInterval: ignore for Bulk transfer */
    $ u$ N$ H: m: g8 ^, n: r

  93. 5 V3 W& q& _. N8 k1 R& w
  94.   /*Endpoint IN Descriptor*/                        //IN端点
    0 g/ R3 R% j! [( q
  95.   0x07,   /* bLength: Endpoint Descriptor size */
    5 P9 B" @4 @" T
  96.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    9 L1 v, @: c: T5 u& ^# E
  97.   CDC_IN_EP,                         /* bEndpointAddress */! Q! Z. ]  U: z! }
  98.   0x02,                              /* bmAttributes: Bulk */* @# c9 X& U" n
  99.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    ! @9 O0 o8 b8 R1 p$ A
  100.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    % ]3 X4 g9 F: D8 L8 i- L* |
  101.   0x00,                               /* bInterval: ignore for Bulk transfer */( b2 G: }; c5 a7 C6 s- ?
  102. 2 W: c' K: A9 }
  103.   /*---------------------------------------------------------------------------*/, B2 @/ k$ W. z4 Z: L/ r" o4 Q2 z
  104.   // IAD  Interface Association Descriptor       //这里就是CDC1了,重复CDC0的配置过程,注意有些字段的序号 casojie
      ?- `: m, u) G) i% _+ g
  105.   // 0x08,  // bLength: Interface Descriptor size
    - v9 E! U$ U+ m! Q" i2 q) I  z  e
  106.   // 0x0B,      // bDescriptorType: IAD
    ) v4 w* I1 ]& S. W. u
  107.   // 0x02,  // bFirstInterface                  //太多了,写不下去了,意思和第一个IDA一样的' s$ W) t4 X- t7 C2 i6 T
  108.   // 0x02,  // bInterfaceCount
    4 z" r) K$ q1 I: R3 ^
  109.   // 0x02,  // bFunctionClass: CDC
    & b8 x3 x+ i- h* K
  110.   // 0x02,  // bFunctionSubClass. q& x6 j6 M, V8 u4 p5 w+ K. e
  111.   // 0x01,  // bFunctionProtocol
    7 e4 c7 Q$ J; ], K( O% q( J( N: u0 m
  112.   // 0x02,  // iFunction
    2 O% e! e$ F& V# w) ^3 q
  113. 3 [+ U; M; b: o. L9 l2 H& C  T. v! v
  114. /*Interface Descriptor */
    ( M  L- {- q! _4 p- B
  115.   0x09,   /* bLength: Interface Descriptor size */, S3 e% O2 R. G' c1 ~
  116.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    7 B6 ]* p: p  t
  117.   /* Interface descriptor type */! x8 y, v9 D, z6 }( N9 D, j6 D; w
  118.   0x02,   /* bInterfaceNumber: Number of Interface */( z) p2 U& ]' [2 h# n6 y
  119.   0x00,   /* bAlternateSetting: Alternate setting */
    9 W" y4 Y; L1 N) U1 S1 A
  120.   0x01,   /* bNumEndpoints: One endpoints used */5 N. [) {$ ~2 c1 J. V0 E
  121.   0x02,   /* bInterfaceClass: Communication Interface Class */: i% W% @& L. Q  Q: y6 v) _! w
  122.   0x02,   /* bInterfaceSubClass: Abstract Control Model */; w5 _8 A1 e! {
  123.   0x01,   /* bInterfaceProtocol: Common AT commands */% C1 H! _: P7 C+ S( d$ o, A$ J
  124.   0x00,   /* iInterface: */
    8 z+ _5 p6 m1 l$ [

  125. 4 _8 E$ ^5 o- ^( q% o! w
  126.   // /*Header Functional Descriptor*/; `9 O# e0 t2 j5 \
  127.   // 0x05,   /* bLength: Endpoint Descriptor size */
    ) j# y$ e8 O( z" l2 ?1 D( l
  128.   // 0x24,   /* bDescriptorType: CS_INTERFACE */4 g( F" [& {0 Q3 ~% t- z
  129.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */0 \0 K, ~* z  i% {
  130.   // 0x10,   /* bcdCDC: spec release number */" a$ n2 q7 W7 D. V$ o$ y
  131.   // 0x01,% N% h0 z% A+ y2 J$ D- g7 ^$ f
  132. , \% M! c9 Y4 m* ^. j) l" o" g
  133.   // /*Call Management Functional Descriptor*/
    % j8 M% U0 p: G7 U# n/ H# T6 e$ W
  134.   // 0x05,   /* bFunctionLength */5 D9 w; B; |# G" R' c
  135.   // 0x24,   /* bDescriptorType: CS_INTERFACE */  x" ^7 @$ v' ?" @! P
  136.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */8 I4 V5 C9 A% w# g! C
  137.   // 0x00,   /* bmCapabilities: D0+D1 */2 `3 h& V* B2 a
  138.   // 0x01,   /* bDataInterface: 1 */" ^- }& L3 C. i1 B
  139. 8 Y- c6 }8 L  j, \
  140.   /*ACM Functional Descriptor*/0 ]* Q, q' b) j9 m; z; r- X; q
  141.   0x04,   /* bFunctionLength */
    / h3 E* ^: w- D9 \1 K
  142.   0x24,   /* bDescriptorType: CS_INTERFACE */
    6 c: n/ D( W4 P3 f# |# F" ]
  143.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    ) T5 P( ?( u3 |, Q7 l3 ]0 T3 N  h
  144.   0x0F,   /* bmCapabilities */
    / M4 b8 K7 J/ w) M; z2 Y

  145. 7 r5 q9 P$ N- [4 Z8 B  V$ k
  146.   /*Union Functional Descriptor*/8 f4 r% Q; H$ r  L
  147.   0x05,   /* bFunctionLength */; w9 a. }! u. P! d1 m! ]
  148.   0x24,   /* bDescriptorType: CS_INTERFACE */
    7 [* h0 N. Q$ @. ^5 s/ ?
  149.   0x06,   /* bDescriptorSubtype: Union func desc */0 }! U; T( F. I8 ]. ^3 R
  150.   0x02,   /* bMasterInterface: Communication class interface */
    9 B  P; o; y, v$ x. n6 \
  151.   0x03,   /* bSlaveInterface0: Data Class Interface */
    # J, c* H! I' [
  152. ! K" z7 ^" P. _, m- B, q- S9 h
  153.   // /*Endpoint 2 Descriptor*/- |( k: F1 M- H$ M0 O, P+ k9 u
  154.   0x07,                           /* bLength: Endpoint Descriptor size */
    $ [1 a6 f) r" [
  155.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    / |' i* I: R$ ~6 \3 n5 ]3 c
  156.   CDC_CMD_EP1,                     /* bEndpointAddress */
      m! N, w* S$ x
  157.   0x03,                           /* bmAttributes: Interrupt */
    + s, U0 [0 Z8 t, n* y) H/ V
  158.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */9 Q9 B1 G' Z1 |9 h
  159.   HIBYTE(CDC_CMD_PACKET_SIZE),: r3 c+ R; G8 p
  160.   0x10,                           /* bInterval: */ - x2 I9 K' q! h% s- K' u2 u4 d; A
  161.   /*---------------------------------------------------------------------------*/. u. D9 L& u# ]  X6 P5 M; O
  162. 7 M1 q* P0 d/ }) _, N* T
  163.   /*Data class interface descriptor*/: I* V; V, ^$ X: @% M9 O4 T
  164.   0x09,   /* bLength: Endpoint Descriptor size */# B7 x9 x0 T5 g
  165.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    , f& _4 t. ]7 d9 b. {! c
  166.   0x03,   /* bInterfaceNumber: Number of Interface */
    8 L  j( T, R" ?4 Z# E
  167.   0x00,   /* bAlternateSetting: Alternate setting */
    % y6 i! {) m, n$ j7 @$ `
  168.   0x02,   /* bNumEndpoints: Two endpoints used */- R6 k; F0 a2 Y% `2 B6 F4 h. E
  169.   0x0A,   /* bInterfaceClass: CDC */
    $ k/ \6 d9 R6 ?2 ^3 r9 L$ z$ I
  170.   0x00,   /* bInterfaceSubClass: */
    9 |( f+ q' j) d  A
  171.   0x00,   /* bInterfaceProtocol: */
    9 x/ B7 i, w* B2 L, n
  172.   0x00,   /* iInterface: */' Y9 ]; G3 K7 ?! l  ]5 e3 G

  173. " H7 r$ D* Q  S$ @% [4 V2 A1 b
  174.   /*Endpoint OUT Descriptor*/) n6 s; d2 H- N6 V& \4 M! H
  175.   0x07,   /* bLength: Endpoint Descriptor size */) A7 T! @3 C1 X0 Y
  176.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    : T+ `( M0 u9 C* |' w! T6 I
  177.   CDC_OUT_EP1,                        /* bEndpointAddress */7 m( g" A  ?: Y1 P. [1 X: i: a
  178.   0x02,                              /* bmAttributes: Bulk */$ }- z% ^. s- d6 y
  179.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    / p( V- Z- K7 A$ b' u, B2 ?, K
  180.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),5 Y* m3 y" C' i" S
  181.   0x00,                              /* bInterval: ignore for Bulk transfer */
    ; H) C& E( y/ t9 z3 H5 r

  182. : i& R. u6 U% D+ V6 ^
  183.   /*Endpoint IN Descriptor*/
    , J3 m4 p3 h- E3 _% c2 s) s# F/ C
  184.   0x07,   /* bLength: Endpoint Descriptor size */
    1 z7 }3 L* E4 g8 J, K
  185.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */) f$ g' L8 ?  u& }' S0 {
  186.   CDC_IN_EP1,                         /* bEndpointAddress */: b& J' A! S+ r; a, x* h/ r, i
  187.   0x02,                              /* bmAttributes: Bulk */
    . D9 O: p7 W- ^3 q/ E, a
  188.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */% L0 v' S$ x1 _8 K: O7 P6 y1 \
  189.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    6 t. V) W  @+ K! M) H
  190.   0x00,                               /* bInterval: ignore for Bulk transfer */# m" i' J3 N% j1 M8 h* n( O3 b
  191.   /*---------------------------------------------------------------------------*/
    8 M' m: o/ P: F, b. v! s
  192.   // IAD  Interface Association Descriptor. X9 r5 }  P0 H  g
  193.   // 0x08,  // bLength: Interface Descriptor size
    ! Z# O' }6 c/ ^5 Y" N" p$ p
  194.   // 0x0B,      // bDescriptorType: IAD
    0 r, P( ]% X$ q  Q: u! n
  195.   // 0x04,  // bFirstInterface
    ( S+ C8 e& I! T: D
  196.   // 0x02,  // bInterfaceCount
    & R8 ~3 Z4 M6 ?& D% Y  }1 m8 u0 N
  197.   // 0x02,  // bFunctionClass: CDC
    6 f( {' N' b4 t* _
  198.   // 0x02,  // bFunctionSubClass5 q+ q) }& `9 @& Y/ d* G. W# x
  199.   // 0x01,  // bFunctionProtocol
    + a" K2 P& v; \* v
  200.   // 0x02,  // iFunction
    # w. m) l5 E0 j! ?" R0 h* R( p

  201. ; R& s" q: p% d" c; s8 O2 z% U
  202. /*Interface Descriptor */
    * V3 V5 c2 T* O4 ?: g
  203.   0x09,   /* bLength: Interface Descriptor size */
    " E# G  z/ D/ a
  204.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */$ v+ w0 g: n8 a* R) t
  205.   /* Interface descriptor type */; k4 P! M; C+ g4 z, A
  206.   0x04,   /* bInterfaceNumber: Number of Interface */$ k1 U2 s2 Y1 o0 u7 ]2 B
  207.   0x00,   /* bAlternateSetting: Alternate setting */
    9 g/ P) |' P2 h; e
  208.   0x01,   /* bNumEndpoints: One endpoints used */8 J4 @+ Z; I8 M% [# r+ S
  209.   0x02,   /* bInterfaceClass: Communication Interface Class */# Z4 j. }, k1 y' M9 @
  210.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    , ?* X+ M8 ?7 O. [. d
  211.   0x01,   /* bInterfaceProtocol: Common AT commands */
    ' U. r; [4 A% s: U* c
  212.   0x00,   /* iInterface: */; e1 B4 v% j1 t3 p( N* [6 u! M
  213. % X, L$ S: D! h8 {8 {/ \
  214.   // /*Header Functional Descriptor*/% A0 D. P6 B- m9 T; F
  215.   // 0x05,   /* bLength: Endpoint Descriptor size */
    3 P& ?8 M+ {4 N# K+ L/ z+ C
  216.   // 0x24,   /* bDescriptorType: CS_INTERFACE */( ~& m' K0 M2 J7 m7 f9 g9 h: W
  217.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */
    / r" ^& y% n# ?) U5 m
  218.   // 0x10,   /* bcdCDC: spec release number *// e3 H& N4 u: ~2 f* E
  219.   // 0x01,
    3 L8 Z# ^8 h) T% C  H- v

  220. # g" I, ^' f, o  s& ]; e
  221.   // /*Call Management Functional Descriptor*/& Q9 t* s8 v6 r/ B/ d, T; [
  222.   // 0x05,   /* bFunctionLength */
    3 y" R2 i+ I2 {, N) E
  223.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
    . y* S( r/ ]+ _# d8 U
  224.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */4 R/ d) a. `! ?0 K% ?4 z8 h
  225.   // 0x00,   /* bmCapabilities: D0+D1 */- x8 g6 g: ~1 P, V+ B4 a" ^! f
  226.   // 0x01,   /* bDataInterface: 1 *// n$ @' w3 L7 \/ K) g$ Y3 r$ c& L* J
  227. $ |5 `: c  s$ Y0 C+ }! J0 S
  228.   /*ACM Functional Descriptor*/
    ! \1 k9 L* k' c) [% F
  229.   0x04,   /* bFunctionLength */. v  o6 i) b; X3 P1 I3 T6 l) \
  230.   0x24,   /* bDescriptorType: CS_INTERFACE */7 o8 |0 C+ o* i: T/ H
  231.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    ( w% K9 R5 J5 f9 D" Y, p3 j
  232.   0x0F,   /* bmCapabilities */3 M2 W$ T3 B6 i2 F6 U
  233. ' F* R! t* i5 L$ _
  234.   /*Union Functional Descriptor*/* G5 m3 Z" ?! h, R. s
  235.   0x05,   /* bFunctionLength */
    4 z. Y6 u1 ~0 u
  236.   0x24,   /* bDescriptorType: CS_INTERFACE */% B2 f  k! \- i6 k9 K
  237.   0x06,   /* bDescriptorSubtype: Union func desc */4 s8 p' S+ ?  u6 d
  238.   0x04,   /* bMasterInterface: Communication class interface */
    2 j. b: \9 P0 L
  239.   0x05,   /* bSlaveInterface0: Data Class Interface */' a2 T8 z3 o2 d. H

  240. ! p  P* q" k/ S, g
  241.   // /*Endpoint 2 Descriptor*/
    - ?$ \" l9 [6 {: d/ L) ?6 J
  242.   0x07,                           /* bLength: Endpoint Descriptor size */9 ^' [( b1 S: O% m- `
  243.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    5 L" F, H( ?( i5 F2 ?2 L8 i
  244.   CDC_CMD_EP2,                     /* bEndpointAddress */; G% l; Z, o' p
  245.   0x03,                           /* bmAttributes: Interrupt */8 r" T( z9 ~4 |: J0 i( `* a
  246.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */  r+ K1 f' f: @  x3 V% g7 ^
  247.   HIBYTE(CDC_CMD_PACKET_SIZE),9 s& |8 d9 C! E) A5 }5 D( d
  248.   0x10,                           /* bInterval: */
    ; Q5 m$ x- X( ~+ L. w" P0 D
  249.   /*---------------------------------------------------------------------------*/
    & j2 I. Q* ]# m5 \' @* }0 y
  250. 4 {; {8 D* ]( I  b5 e+ @% I- C- Y
  251.   /*Data class interface descriptor*/
    0 N) j3 ?( |; y) v: k* l
  252.   0x09,   /* bLength: Endpoint Descriptor size */3 l/ h( Z$ |$ `% F+ t# i
  253.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */) K2 T6 W& y) V, Z9 A: l, J3 N
  254.   0x05,   /* bInterfaceNumber: Number of Interface */
    # C; q; T9 s" ?* Q5 H
  255.   0x00,   /* bAlternateSetting: Alternate setting *// @; B! _- K: P" d* M( v
  256.   0x02,   /* bNumEndpoints: Two endpoints used */
    : ~0 {1 v& G1 i, a) R
  257.   0x0A,   /* bInterfaceClass: CDC */
    7 l: n( z* Y2 g% o1 M
  258.   0x00,   /* bInterfaceSubClass: */, e' `0 X0 m/ S: g
  259.   0x00,   /* bInterfaceProtocol: */
    : ^, I5 c- E% h8 A0 D
  260.   0x00,   /* iInterface: */' \' y( `+ s7 z( T7 V* E$ ~

  261. " L7 I0 N. a3 t8 j$ a
  262.   /*Endpoint OUT Descriptor*// W( w( _& z. }
  263.   0x07,   /* bLength: Endpoint Descriptor size */
    3 k) G" h: J6 A* X; v
  264.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    , p6 b. l, Z0 W1 F8 ]  d
  265.   CDC_OUT_EP2,                        /* bEndpointAddress */
    0 r3 w! B4 \8 D
  266.   0x02,                              /* bmAttributes: Bulk */
      [, J" c1 {; _+ J
  267.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    " ^% w" G6 [2 }- W; \* Q2 ?) u
  268.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    9 U3 [! \+ K& E& J  Y6 }5 i
  269.   0x00,                              /* bInterval: ignore for Bulk transfer */5 i; K' {8 q% k9 J2 x9 A( |, F& ^
  270. - Q  h& `: b( L, _! L1 N
  271.   /*Endpoint IN Descriptor*/+ L( f; X1 {2 n% ^& Q
  272.   0x07,   /* bLength: Endpoint Descriptor size */: p9 e; y! g$ Z" t
  273.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */$ N; J. J& l% Q! p
  274.   CDC_IN_EP2,                         /* bEndpointAddress */! N" U4 `* f1 g# G' M
  275.   0x02,                              /* bmAttributes: Bulk */8 J# m+ a* M1 Q  K, B% h
  276.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */% w" n8 A) W2 E( G" |
  277.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    6 x1 x+ T- I6 e- }" v2 z4 ]
  278.   0x00,                               /* bInterval: ignore for Bulk transfer */3 X# m' Z$ D  Y% W7 C

  279. , e9 B9 \/ u$ J2 J5 V+ }( e9 k
  280.   /*---------------------------------------------------------------------------*/
    7 U1 W' {2 V5 {
  281.   // IAD  Interface Association Descriptor
    ) G- p5 t6 a& e; E0 k0 \* r8 w
  282.   // 0x08,  // bLength: Interface Descriptor size
    . W3 M: \! @2 C% ^9 S: g
  283.   // 0x0B,      // bDescriptorType: IAD- z0 T% \2 f. a5 G7 R
  284.   // 0x06,  // bFirstInterface7 M0 `0 ?  d. l( s" e+ U
  285.   // 0x02,  // bInterfaceCount7 d7 g3 J" Y) O8 I7 M& a% C; I
  286.   // 0x02,  // bFunctionClass: CDC2 M& t$ C1 G& U' F1 H8 f
  287.   // 0x02,  // bFunctionSubClass
    ' F" c* V9 }! ~& |( d# {4 x
  288.   // 0x01,  // bFunctionProtocol
    , ]3 k$ |% {: h/ a" p5 w
  289.   // 0x02,  // iFunction7 T# @' S, h7 j* Z3 \

  290. ( D% q9 N7 G9 J/ e  r* |$ ^7 E. G
  291. /*Interface Descriptor *// p% A! n* P; s/ H; @+ K4 i: {
  292.   0x09,   /* bLength: Interface Descriptor size */
    1 i$ v, z. |7 k6 v
  293.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */8 K2 D' [, A# ]8 I4 g
  294.   /* Interface descriptor type */& e- A2 B* b  e# \0 T
  295.   0x06,   /* bInterfaceNumber: Number of Interface */
    8 J1 E2 S# z0 y4 R" j: O
  296.   0x00,   /* bAlternateSetting: Alternate setting */$ Z6 k8 @* x' Y' A" J- T4 l5 h
  297.   0x01,   /* bNumEndpoints: One endpoints used */
    / P+ [  s- Q. L, b3 j
  298.   0x02,   /* bInterfaceClass: Communication Interface Class */
    $ |5 _9 R8 A) j+ F1 D& H
  299.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    , S! A3 O* P; ^# s! p+ f
  300.   0x01,   /* bInterfaceProtocol: Common AT commands */) k" n  [9 }$ ^2 x$ X
  301.   0x00,   /* iInterface: */
    : k' S: |' x' C1 S  N, @
  302. 5 _3 E3 N' V& j# w& Z
  303.   // /*Header Functional Descriptor*/
    # U+ ^5 u* X2 M  b4 J
  304.   // 0x05,   /* bLength: Endpoint Descriptor size */) a2 C& v( D7 y
  305.   // 0x24,   /* bDescriptorType: CS_INTERFACE */# |: a; m% a5 `6 J4 b2 g/ Z
  306.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */
    9 v# h. A6 z' _$ l1 i7 e8 t
  307.   // 0x10,   /* bcdCDC: spec release number */
    1 I, [" J4 L: w, d4 d6 O
  308.   // 0x01,/ H0 c* a  c2 F$ B% M8 y% d' B
  309. ' o2 t1 s4 j2 i0 O7 a
  310.   // /*Call Management Functional Descriptor*/
    5 H* J' d  z- x+ _7 B! t9 u
  311.   // 0x05,   /* bFunctionLength */
    # V) R3 P3 g' i; |" W2 z( B! h
  312.   // 0x24,   /* bDescriptorType: CS_INTERFACE */8 R6 y# p1 o: u; h7 h( G
  313.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */
    * v0 R" K- W( l! [0 o
  314.   // 0x00,   /* bmCapabilities: D0+D1 *// l8 ?) }; ?7 K6 h7 D) R) z
  315.   // 0x01,   /* bDataInterface: 1 */
    + S0 S/ O5 B6 F' c: l" _2 a
  316. ( D4 H: p0 Q' V4 I
  317.   /*ACM Functional Descriptor*/9 i5 q* Y! h2 Z! f8 m: ?# i
  318.   0x04,   /* bFunctionLength */
    1 I' D5 d0 V0 `" D9 o( C
  319.   0x24,   /* bDescriptorType: CS_INTERFACE */8 k+ R" d# n" a8 z% ]$ E2 B
  320.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */' C8 }1 m# a3 g4 ]
  321.   0x0F,   /* bmCapabilities */5 h6 ?1 Z. T/ J1 Y9 R
  322.   [! f7 \4 C& L% o' B
  323.   /*Union Functional Descriptor*/- O1 @) k6 M# V! ^
  324.   0x05,   /* bFunctionLength */- m1 r9 I8 z1 v
  325.   0x24,   /* bDescriptorType: CS_INTERFACE */
    % v5 d- e1 d, J; C% K. G7 J8 r
  326.   0x06,   /* bDescriptorSubtype: Union func desc */1 R+ s& g/ a& X2 e; E0 R+ ^& V
  327.   0x06,   /* bMasterInterface: Communication class interface */
    6 L, g% R  f+ G& a/ N: p  w
  328.   0x07,   /* bSlaveInterface0: Data Class Interface */1 H5 v$ i# a+ X

  329. 9 j' T  f5 @- B' H6 j
  330.   /*Endpoint 2 Descriptor*/2 |& m1 e  t) Z7 b5 a6 d+ _
  331.   0x07,                           /* bLength: Endpoint Descriptor size */
    ' ]; B& T6 }( i2 n1 d! _3 ~% e
  332.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */( v, M8 a. O/ T1 J2 T! Q( Y. ?5 z
  333.   CDC_CMD_EP3,                     /* bEndpointAddress */5 N3 y9 ]& u7 U
  334.   0x03,                           /* bmAttributes: Interrupt */0 ^2 s" J" L) L  S% R2 i& c0 ^
  335.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */* z" [; f) Y/ O7 i! L
  336.   HIBYTE(CDC_CMD_PACKET_SIZE),
    7 A# o. b+ q5 [6 W3 x
  337.   0x10,                           /* bInterval: */ 1 `, p9 |& t% d- ?" K; j4 ?
  338.   /*---------------------------------------------------------------------------*/6 B& B' v- g) Y

  339. " o  Z2 z2 c! v) K: k
  340.   /*Data class interface descriptor*/; n- }# E( T/ P. K9 D
  341.   0x09,   /* bLength: Endpoint Descriptor size */
    - r1 Y: o, p2 W$ K' @& u
  342.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */$ f7 a0 ?7 r; j. F; S( }; l
  343.   0x07,   /* bInterfaceNumber: Number of Interface */3 `; M- f- Y( _& g( N; [8 P
  344.   0x00,   /* bAlternateSetting: Alternate setting */
    $ `% U* F8 ?: z* i# T( {) `
  345.   0x02,   /* bNumEndpoints: Two endpoints used */
    1 u+ F* [: o$ w& o( T
  346.   0x0A,   /* bInterfaceClass: CDC */
    ! L& l" l# z- q; A7 Z
  347.   0x00,   /* bInterfaceSubClass: */$ l2 p* E: e& Q3 h
  348.   0x00,   /* bInterfaceProtocol: */8 {% V! N$ I% g" a3 G. Y! {
  349.   0x00,   /* iInterface: */
      b$ H6 l5 p( F
  350. $ j  _3 s% u3 q( H
  351.   /*Endpoint OUT Descriptor*/
    # w) K- I2 h% X! ^
  352.   0x07,   /* bLength: Endpoint Descriptor size */
    5 J9 Q8 d4 A$ e, G: z/ w; l$ ^# B
  353.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */% j6 ~) z8 ?3 b# J( @
  354.   CDC_OUT_EP3,                        /* bEndpointAddress */3 r* C  t. q% r, \( p7 o; D; H2 _
  355.   0x02,                              /* bmAttributes: Bulk */
    ( o0 F' J+ b$ E$ {+ Z
  356.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    ! @8 Z  C& U  ^3 [
  357.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    , a5 R/ e' z. r2 J0 N7 e" j/ T
  358.   0x00,                              /* bInterval: ignore for Bulk transfer */9 J0 Q: {# N- `
  359. , S  e6 f7 Z8 t+ t
  360.   /*Endpoint IN Descriptor*/
    . ~! ?' z6 z$ `6 X9 M8 w* H" R
  361.   0x07,   /* bLength: Endpoint Descriptor size */
    ; e. k- z4 T  q4 p: Y  k
  362.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */2 \* Q" c, L. ]0 ?3 |, z) g. {
  363.   CDC_IN_EP3,                         /* bEndpointAddress */
    & j, y% O% b) Z, g
  364.   0x02,                              /* bmAttributes: Bulk *// `0 D) L2 A6 H( x, \' W
  365.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */5 \& p" i4 a# Y+ B
  366.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    0 D; \9 Y" a$ B8 a
  367.   0x00,                               /* bInterval: ignore for Bulk transfer */
    $ x9 [7 v" `/ k2 V
  368.   O% `( n1 c3 c& ]2 b8 q5 O3 K
  369. //   /*---------------------------------------------------------------------------*/
    ! S% j& J9 F6 z  H7 D
  370. //   // IAD  Interface Association Descriptor
    6 u9 W& Q3 T$ H4 n' R) B
  371. //   // 0x08,   // bLength: Interface Descriptor size
    ! R# l( ]/ |" }0 y# s, U  h6 }! ~
  372. //   // 0x0B,       // bDescriptorType: IAD
    - |; Z3 Q, G. a! [5 L
  373. //   // 0x08,   // bFirstInterface
    : U- _& M8 m5 e, o0 |5 U  ~
  374. //   // 0x02,   // bInterfaceCount
    ! B& g: d: f8 X
  375. //   // 0x02,   // bFunctionClass: CDC' x1 u3 A7 N2 M8 b+ `$ F
  376. //   // 0x02,   // bFunctionSubClass
    1 \; C1 g9 g: U
  377. //   // 0x01,   // bFunctionProtocol & b6 D# ?1 ^; T7 O' I
  378. //   // 0x02,   // iFunction8 R& K0 ]5 T0 t9 n8 C/ s
  379. + H$ J7 S7 `" m2 h0 Q' q
  380. /*Interface Descriptor */
    2 A2 H( E$ X! |1 l/ I7 c4 A) K& h3 \
  381.   0x09,   /* bLength: Interface Descriptor size */
    - y. w! Y7 j+ l! o9 E+ d2 V
  382.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */- ?& g% [/ D" i+ Q1 S2 X) j
  383.   /* Interface descriptor type */
    / W' X4 n3 O9 D6 t
  384.   0x08,   /* bInterfaceNumber: Number of Interface */% g- D; ]( x1 c* L$ b
  385.   0x00,   /* bAlternateSetting: Alternate setting */1 _% E2 U! S6 z. _& t/ S" `
  386.   0x01,   /* bNumEndpoints: One endpoints used */
    % N- N4 u) x( x
  387.   0x02,   /* bInterfaceClass: Communication Interface Class */% I' S: L9 r: Z- a- m- l
  388.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    / ~* r; b) S. D7 J6 j/ @# ^
  389.   0x01,   /* bInterfaceProtocol: Common AT commands */
    ) t( a+ d$ H! I: O
  390.   0x00,   /* iInterface: */
    4 Q9 ~3 g( o" b2 {" @" f2 H; B
  391. ' f) ?3 G7 d; `3 ]1 Q1 K
  392.   // /*Header Functional Descriptor*/
    3 {% }  |/ h/ @/ ?
  393.   // 0x05,   /* bLength: Endpoint Descriptor size */
    1 ~0 `; L+ R6 V; g9 k
  394.   // 0x24,   /* bDescriptorType: CS_INTERFACE */4 R! D0 R7 N5 ]3 y
  395.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */# K. _7 H" p2 c% F% G/ h+ {( Y
  396.   // 0x10,   /* bcdCDC: spec release number */
    ( _8 y% L0 F  ~0 G. S0 L
  397.   // 0x01,
    ' E3 }, z) f  P5 M3 p" U
  398. ( Q0 c7 e, F+ Y: D" p$ @
  399.   // /*Call Management Functional Descriptor*/
    ! |  J5 q) r9 x' [' h& }+ x# I4 \
  400.   // 0x05,   /* bFunctionLength */1 S* N" y, k1 A& Q% z& e
  401.   // 0x24,   /* bDescriptorType: CS_INTERFACE */: S2 r9 H) X+ W0 D5 r5 O# G0 }
  402.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */1 e9 N3 u$ A  h4 v6 U! d$ x
  403.   // 0x00,   /* bmCapabilities: D0+D1 */1 o8 N9 ~' C, q  e6 s: O" J6 Q
  404.   // 0x01,   /* bDataInterface: 1 */; i7 d* h! _1 k: a8 w* T8 b
  405. / w+ Q) b( ~1 M- ~; j# w; B; B9 U% y- d
  406.   /*ACM Functional Descriptor*/( G# `5 w: B: {$ z2 `9 I
  407.   0x04,   /* bFunctionLength */
    * P: L- I+ D% S# v3 X* [( i% {6 {
  408.   0x24,   /* bDescriptorType: CS_INTERFACE */
    & @8 e0 W2 D2 |
  409.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */+ e$ v% c6 i- P* T# E/ J4 F: w
  410.   0x0F,   /* bmCapabilities */' P: W: A: B& R" N
  411. 3 X0 I$ E& e+ x: W
  412.   /*Union Functional Descriptor*/7 W; M7 I# K$ O  Y- f8 c
  413.   0x05,   /* bFunctionLength */
    ( z# ]! `) b8 N6 |) c
  414.   0x24,   /* bDescriptorType: CS_INTERFACE */. m; A; V: j, K
  415.   0x06,   /* bDescriptorSubtype: Union func desc */5 A4 H, n5 Y. _+ h
  416.   0x08,   /* bMasterInterface: Communication class interface */; m" Z& @9 j7 U  C- u6 z+ k
  417.   0x09,   /* bSlaveInterface0: Data Class Interface */3 R6 y1 W9 ?* N3 ]- g1 P! N

  418. * `; a# x1 K( A5 _# \0 i
  419.   /*Endpoint 2 Descriptor*/7 t" H# c  b: H2 a
  420.   0x07,                           /* bLength: Endpoint Descriptor size */, H" e$ }# }1 m% R! U* T0 t
  421.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */7 e7 q8 r2 H3 H) O- [
  422.   CDC_CMD_EP4,                     /* bEndpointAddress */( _. \$ T2 \  t; Y: ?8 A% k
  423.   0x03,                           /* bmAttributes: Interrupt */
    3 F/ u  Y% X) c$ ~0 e, x
  424.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */8 U* P" h. M7 L
  425.   HIBYTE(CDC_CMD_PACKET_SIZE),6 U/ h6 d' f2 k2 X% Q
  426.   0x10,                           /* bInterval: */
    + k) r2 y; r, j9 L  Z
  427.   /*---------------------------------------------------------------------------*/
    5 \, P4 i6 F& ?: U5 V
  428.   /*
    2 {0 k$ ]2 a( @4 }8 ]0 ^
  429.   /*Data class interface descriptor*/
    . h7 p$ l  A1 y0 C6 O' T& k
  430.   0x09,   /* bLength: Endpoint Descriptor size */3 _' T2 o- T- P. }  z2 \$ v
  431.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */- q9 A) e& A; Y' l' N4 Z+ F& K* t
  432.   0x09,   /* bInterfaceNumber: Number of Interface */* M1 t0 c" j4 }! F
  433.   0x00,   /* bAlternateSetting: Alternate setting */9 Y) b) V4 H" }# j
  434.   0x02,   /* bNumEndpoints: Two endpoints used */
    5 C' L5 l/ t/ y, g+ y( r
  435.   0x0A,   /* bInterfaceClass: CDC */
    8 ]9 E& ?' Z1 ~( p. Z
  436.   0x00,   /* bInterfaceSubClass: */
    6 q& q( X' F2 y, J: @( m/ S* B
  437.   0x00,   /* bInterfaceProtocol: */7 j3 H2 S$ u7 L
  438.   0x00,   /* iInterface: */) l/ q! \% l! ^6 D7 r! E
  439. , l- U4 x8 B4 _: y( V+ S! N7 ]
  440.   /*Endpoint OUT Descriptor*/
    , J7 x2 L7 a+ a! z
  441.   0x07,   /* bLength: Endpoint Descriptor size */
      J8 |+ n' L; k0 T
  442.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    0 E7 C  u3 J5 X' f
  443.   CDC_OUT_EP4,                        /* bEndpointAddress */( ]6 Q, T' o8 b" J% n& Q
  444.   0x02,                              /* bmAttributes: Bulk */
    ' p) Q& U2 H) t$ W( y) Q
  445.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    " @, q- w: ?  R) v& }
  446.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    ' B* a, M& N. A1 h, l
  447.   0x00,                              /* bInterval: ignore for Bulk transfer */
    * o! I. z$ q2 s8 K

  448. + z1 A3 C9 W# k& ]& r0 }" z5 X
  449.   /*Endpoint IN Descriptor*/% A% Q# J! w/ b7 t8 e& O. }
  450.   0x07,   /* bLength: Endpoint Descriptor size */
    8 c* A) Z1 E3 n. v6 [
  451.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    7 w8 z  V$ ?; H. N1 ?
  452.   CDC_IN_EP4,                         /* bEndpointAddress */& ~, l+ w9 c$ U* d9 V
  453.   0x02,                              /* bmAttributes: Bulk */
    : l) D. X# F) I" }* r/ z
  454.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    $ X' ?9 n3 M+ K6 s2 _# X  N
  455.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),& ~  e5 ?. X6 ^, b
  456.   0x00                               /* bInterval: ignore for Bulk transfer */
    0 |. J8 i5 x9 r1 B
  457. }
复制代码

/ s5 {3 A1 N" }6 y
; F4 `0 t- H7 A; ?5 u+ R& V4 X
  • 为什么上面有些描述符被注释掉了?
  • 配置5个CDC如果描述符都写上了,这个结构体就超过了255个字节大小,超过了USB2.0最大配置描述符长度
  • 在我的项目中,IAD和联合描述符(/Union Functional Descriptor/)功能一样,我这里注释IAD描述符,不会影响USB,但在windows平台下,它认的是IAD描述符,这个时候就可以注释联合描述符,打开IAD描述符,总之,省略一些非必要描述,减少长度, p6 Z0 k: ~' a
  • 这里的坑很多很多,需要很耐心,配错一个字段,千奇百怪的问题就来了
    # \+ ^  w# a$ \7 a9 f

    % J1 J8 l% _, N& T/ B* c3 ?
3.4 配置PMA---USB硬件缓存
  • 这里又有坑了,我把我知道的都说出
      L# E) A! c& x( D: \- c
3.4.1 PMA是啥?
  • 此部分感谢一个大佬的帖子,理解来源与它
  • 这个PMA的作用就是USB设备模块用来实现MCU与主机进行数据通信的一个专门的数据缓冲区,我们称之为USB硬件缓冲区。说得具体点就是USB模块把来自主机的数据接收进来后先放到PMA,然后再被拷贝到用户数据缓存区;或者MCU要发送到主机的数据,先从用户数据缓存区拷贝**MA,再通过USB模块负责发送给主机。
    8 I7 p+ {- k+ I8 p; G9 f/ Q
4 U, {) P9 X& b; i0 ?8 P! \

) u6 X9 n4 \+ A: ~5 I- }3.4.2 5个CDC的PMA怎么配置?
  • 啥也不说,先上代码) N2 [$ ^) N. D) s( @7 {3 \) ~/ q

% y3 \+ P$ {, L* X) M
# C- ~  b& X) H- m. u: |& @
  1. u_int16_t ep_addR=0x70; //起始分配地址: 这里是大坑 casojie
    * l/ M- E" D: L1 w4 O
  2. u_int8_t ep_addr_size=64;
    ( R1 B! }  S! w1 i  ~
  3. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;   //此端点是用于USB枚举和基本的通信使用,默认就有,且不可省去: h' j1 U8 T- C8 y" H6 E( p; Z1 @
  4. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  d4 q+ i8 X! F: l; z+ X9 y, d
  5. /* USER CODE END EndPoint_Configuration */
    , O: S% q+ x9 E  v! I% ^. m
  6. //CDC0 每个端点都分配了64B7 u8 q. D6 y& S/ c1 L% C* n; ~
  7. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;/ E# q1 U, z' m2 s: p
  8. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
    ! q' C: H( S3 E( d1 [

  9. $ V& ~% L. v: [* h
  10. //CDC1                                                                                                //+59 \3 p6 n$ L' L7 F& G
  11. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP1, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  //192 258
    ' i1 V, w9 U- |; M6 S
  12. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP1 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;    //272 2A8
    6 s1 N  R8 Q% F6 E

  13. / ?- h* z- j% Y% ^# s1 r4 ?+ z9 q
  14. //CDC2
    ; X2 n9 Q3 B$ G! `" K9 r, R
  15. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP2 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size; //0x270
    & p3 z- H3 K& h$ w: R* ^/ A
  16. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP2 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;//0x2C0
    * Z% d# g& `; T6 W: s( c8 \

  17. 1 @3 l& a8 y' ~5 f
  18. //CDC3
    9 d8 D) k, W3 p9 v) A4 n" m0 Z
  19. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP3, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  //192 258 0x1E0
    ) e, l& c& ~1 W4 {- m0 w2 T  e
  20. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP3 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
    + s4 j. x8 h5 R- M, t$ N

  21. 4 r1 X+ {* T( i2 f
  22. //CDC4" I! E  g) Q1 G% l$ W
  23. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP4, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  3 q) w7 D$ v: @. m0 D
  24. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP4 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
复制代码

1 g& T3 a7 u  z: J1 N( ?  F: f) s3 |4 q
  • PMA图(我理解的)
    / ~& W9 \+ `( O0 L" {9 I4 \
5 p: {2 q+ l( `6 y' Q$ t& x8 s
  • 在PMA的开头部分,是用于记录信息的,这些信息就是:端点缓存区的起始地址:说这简单点,里面写了端点0的缓存区的起始地址是X,端点1的缓冲区起始地址是Y等等
  • 由此可见,当使用的端点数量比较多时,信息记录区索要的空间就比较大,反之,就小,需要动态调整
  • 由大佬的帖子可知,记录一个端点的起始地址信息需要8字节,那么我们五个CDC,则5x2(IN,OUT)=10,再加上0x80 ,0x00端点,一共12个.则12*8=76字节
  • 因此,端点(0x00)分配的地址需要往后偏移,默认的不行,如这次需要76字节的大小,换成16进制,0x4C,我设置了0x70>0x4C,默认的太小了,会导致部分信息记录区被端点0的数据覆盖,而导致部分端点无法使用.' f( _8 F6 ^* Z2 n2 ~/ X
$ k( c# Z7 M2 z# S/ l% z
3 ~# d; _& K; l* D
4.修改USB初始化代码,新增对新端点的初始化$ L- M" u! G* y) X. i
8 Y5 h+ ]; Y3 c  B4 E" I1 ~
  1. static uint8_t  USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
    4 ^" [! h- X: x
  2. {
    - Y! B( T7 {0 C
  3.   uint8_t ret = 0U;
    ' f8 |, w: d+ V# o7 k, k, K- q2 h
  4.   USBD_CDC_HandleTypeDef   *hcdc;
    # B/ N& ^( q9 n) P* i* t
  5. ' g( c4 [) N- i
  6.   if (pdev->dev_speed == USBD_SPEED_HIGH)
    / T9 h+ s, ^; Y  Y7 `
  7.   {. i+ S9 q) r8 R$ \+ d3 z
  8.     /* Open EP IN */
    : j& ]: j6 o. L  a! a3 n  {! Q
  9.     USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
    5 S0 X: c- z* D3 a! K/ y
  10.                    CDC_DATA_HS_IN_PACKET_SIZE);
    ; ?: a& v/ K; i- [4 w: V

  11. 3 R) b* H, l) @- B- T( \
  12.     pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
    % c, {: `$ w6 v- l* L0 A

  13. / ?& T+ z! ]+ s+ c2 A) |" Y; G! V
  14.     /* Open EP OUT */
    9 \5 ^9 f) v; {
  15.     USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,3 ]$ }( j: y& q6 y  K( Q  f4 b9 t5 n
  16.                    CDC_DATA_HS_OUT_PACKET_SIZE);
    " \+ m! V& Z% A, V" g+ ^

  17. - M  k! I3 x8 _3 y+ Q( @1 _
  18.     pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;! }+ U1 F" b+ P3 a( Z, G; I6 x
  19. 8 D$ u8 x$ O# u  Y9 t3 z
  20.   }
    * A& H  E; D9 C
  21.   else; s/ S" k; E0 ~9 H2 T$ N9 H
  22.   {
    7 `6 o, O  D1 Z
  23.     /* Open EP IN */
    + ?/ _' j* F: ?+ O5 p
  24.      USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK," }* Q; a* D, b6 R6 ~
  25.                    CDC_DATA_FS_IN_PACKET_SIZE);
    5 y4 K- }1 n4 F

  26. , |$ W( N/ s7 G5 J2 Y
  27.      pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;! [/ a! t) }) t2 ^2 ~6 {

  28. $ L( W) F5 R+ p8 \* i
  29.     /* Open EP OUT */# `+ }1 {  h+ F- ~
  30.      USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
    5 @- \0 E/ g) ~% e, }9 l, l
  31.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    $ W  J* W5 z" p1 o6 g

  32. - U* ]3 {1 [" m) U
  33.      pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;9 G* y( E* I6 r; m! R

  34. + p$ w/ L7 x) V) h' \  f

  35. 8 ?/ x+ _7 E, n  G: G
  36.         /* Open EP IN */
    2 T4 F' n, ]1 V4 ]5 Q: _
  37.      USBD_LL_OpenEP(pdev, CDC_IN_EP1, USBD_EP_TYPE_BULK,; l  q% `( p9 P$ U+ S
  38.                    CDC_DATA_FS_IN_PACKET_SIZE);3 g7 K% g" p! x& i
  39.   x) S3 Q  u" T$ K2 g
  40.      pdev->ep_in[CDC_IN_EP1 & 0xFU].is_used = 1U;
    2 x) ]: G/ @7 l9 f0 a5 C

  41. 0 f* e  q/ i& g- E( |( M$ B5 \
  42.     /* Open EP OUT */
    6 E3 @' h- x* m  y! Y) [6 \
  43.      USBD_LL_OpenEP(pdev, CDC_OUT_EP1, USBD_EP_TYPE_BULK,5 A6 L) R6 A' S& P
  44.                    CDC_DATA_FS_OUT_PACKET_SIZE);7 i- l" g0 v4 ^

  45. 3 u, Y+ ]/ R# X# S8 g; u9 M) G
  46.      pdev->ep_out[CDC_OUT_EP1 & 0xFU].is_used = 1U;
    , v+ G8 Z6 @. `* P: e2 Y6 p

  47. ( I  d' W" @! p! J0 O/ r

  48. 2 `0 q; c* r( R' t- J

  49. 2 ?# n% w! t, q& D
  50. //--------------------------------------------------------------------
    & U  w: _% {) @# o0 `  T
  51.        /* Open EP IN */: e; Y# U4 |3 |% M- E1 w
  52.      USBD_LL_OpenEP(pdev, CDC_IN_EP2, USBD_EP_TYPE_BULK,) t3 Y' S0 u6 S, N: R
  53.                    CDC_DATA_FS_IN_PACKET_SIZE);, W  }* \9 {" B% w1 I4 q7 X+ |

  54. $ o$ x1 I$ _5 [2 c
  55.     pdev->ep_in[CDC_IN_EP2 & 0xFU].is_used = 1U;
    1 l, C  K" U& k8 s4 V
  56. * a8 V; S1 I/ x7 x
  57.     /* Open EP OUT */0 e) n8 |% D& a$ p" @6 r
  58.     USBD_LL_OpenEP(pdev, CDC_OUT_EP2, USBD_EP_TYPE_BULK,7 `& J/ e; X# ~$ h
  59.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    4 t8 ~) s1 m, [5 F) a

  60. " f+ w! c% E6 h6 k* C9 s
  61.     pdev->ep_out[CDC_OUT_EP2 & 0xFU].is_used = 1U;
    " E, i; d) ?# k' _  y4 G  f

  62. ' K- h) J) J  S4 X: C. Q4 c

  63. % ~) H8 D7 d) b5 b* a
  64.    //-------------------------5---------------------
    $ ]1 S- c( W- ?
  65.            /* Open EP IN */
    , i7 m9 \+ w/ m9 o  [  \5 G
  66.     USBD_LL_OpenEP(pdev, CDC_IN_EP3, USBD_EP_TYPE_BULK,+ G; d5 Q- S& ]) v# r
  67.                    CDC_DATA_FS_IN_PACKET_SIZE);3 M+ y- E* U. ^6 D) x
  68. ; Y; x7 F5 G5 c- r
  69.     pdev->ep_in[CDC_IN_EP3 & 0xFU].is_used = 1U;: {" z( [4 G( ^& x2 B, {5 h
  70. 3 f* C1 M9 y2 Q: U% H9 x
  71.     /* Open EP OUT */
    2 [# c9 g7 _# s, {  F$ m! k! z
  72.     USBD_LL_OpenEP(pdev, CDC_OUT_EP3, USBD_EP_TYPE_BULK,/ t4 u, |* n: D$ T( [7 u
  73.                    CDC_DATA_FS_OUT_PACKET_SIZE);6 L! }: Z; f/ @- ^& z& J

  74. ' Z+ ?1 P2 Z1 }& w! i
  75.     pdev->ep_out[CDC_OUT_EP3 & 0xFU].is_used = 1U;* m4 T; q" Q. z; _) y

  76. $ T1 {8 I. s3 _
  77.     //-------------------------5---------------------. b& e3 f' T( l# D. ?! l* w
  78. & A% f: }2 C- V7 N5 n1 R/ ?
  79.            /* Open EP IN */
    - h( P9 c+ E4 s" E) E$ r; Z0 [
  80.     USBD_LL_OpenEP(pdev, CDC_IN_EP4, USBD_EP_TYPE_BULK,8 j' Y4 Y2 S8 ?
  81.                    CDC_DATA_FS_IN_PACKET_SIZE);
    . o4 r6 J' j  C" v) P' i2 G

  82. * I6 |$ Y" E1 b3 D# p2 }/ `
  83.     pdev->ep_in[CDC_IN_EP4 & 0xFU].is_used = 1U;
    / W7 Z; u# `, o, S# Y

  84. 1 X6 u' N1 n; t4 Q) Q
  85.     /* Open EP OUT */6 Q, t/ U, a. o7 q' ^# q4 D
  86.     USBD_LL_OpenEP(pdev, CDC_OUT_EP4, USBD_EP_TYPE_BULK,
    , u, G* y$ z5 @- M  D
  87.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    , P$ ]; [! x' T  L2 h6 D8 F

  88. 9 q0 K- r0 f5 T( K% C! y" v
  89.     pdev->ep_out[CDC_OUT_EP4 & 0xFU].is_used = 1U;
    1 G  L% f& c; U6 _- l6 o. Y8 @- q
  90. 4 H( C4 l, K2 a  N2 k) S" y
  91.   }
    * j% C) ?9 L, ?: l( r8 ]( Y: r
  92.   /* Open Command IN EP *///控制端口无效,不要取消注释
    6 j! h( g1 A6 f: R
  93. //  USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);6 _3 S' D( Z% |+ ]% f" N% Z
  94. //  pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;- c  w: H, V5 o, h% _5 ^
  95. 9 c/ b1 s+ r- q7 k

  96. - P6 ~; D- e, {" l4 r5 j8 Z6 p9 g! u
  97. //   USBD_LL_OpenEP(pdev, CDC_CMD_EP1, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);' D% t+ `& k- V5 y6 k- i- w* n4 p
  98. //   pdev->ep_in[CDC_CMD_EP1 & 0xFU].is_used = 1U;+ u8 z7 i2 y' I
  99. 1 X3 Q/ L2 _2 p% y" Q' q
  100. 2 V: ^7 R4 V# g# w7 {- x  t
  101. //     USBD_LL_OpenEP(pdev, CDC_CMD_EP2, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);- g, I: B" O; s* O4 w2 L
  102. //   pdev->ep_in[CDC_CMD_EP2 & 0xFU].is_used = 1U;/ x& c* \+ I$ s# v2 k; Z2 N

  103. . [& N2 R" s! g. }& O
  104. 6 z$ w- f" p4 v2 a" o
  105.   //   USBD_LL_OpenEP(pdev, CDC_CMD_EP3, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);: G+ T+ c+ J. J3 _; l1 i
  106.   // pdev->ep_in[CDC_CMD_EP3 & 0xFU].is_used = 1U;9 W$ Y# x* f0 W. ?
  107. # J) J+ |9 ]2 O% l* r' w* l8 z# t; E6 |; [
  108.   pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
    $ n5 v2 `& D, B9 c$ z( U
  109. 5 \1 o& A# o7 B( p- m
  110.   if (pdev->pClassData == NULL)
    0 _' }/ b; O  s( k2 V+ Y
  111.   {
    7 G6 K3 z/ e! N* @. V
  112.     ret = 1U;$ u2 U4 O0 i4 g$ e+ S
  113.   }
    + h4 k" O# j! F& e
  114.   else8 y% q, A/ F0 X. m
  115.   {  _5 L3 ?& u$ a5 L
  116.     hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
    0 e- ^% A, z. ^2 i# @

  117. ) Q$ T. B. [! W/ u# W% A- }
  118.     /* Init  physical Interface components */
    + W  Q' W  F( x$ U; U# B4 |1 G" b
  119.     ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
    ! h9 R# H' A, D" Q) y: p7 C# I2 b1 R
  120. 2 ]" c) z7 a# n! C$ U5 x$ a
  121.     /* Init Xfer states */" q. E+ z% _- R4 J
  122.     hcdc->TxState = 0U;
    % Y$ Z" q4 l0 o+ }" }
  123.     hcdc->RxState = 0U;5 D+ M2 R0 M9 @5 R  n
  124. . n% Q* }, Q( ^7 ]% c
  125.     if (pdev->dev_speed == USBD_SPEED_HIGH)# O8 t- q" E8 _* `# D
  126.     {0 ^% g; \4 ]: n
  127.       /* Prepare Out endpoint to receive next packet */
    . o, q  ]9 I4 _; W1 B
  128.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,- {2 L" z: o* P; ?
  129.                              CDC_DATA_HS_OUT_PACKET_SIZE);
    ! E* C- B( U% _) M( M9 q
  130.     }9 X% B7 G) H+ t/ x2 |% D" J- V# t
  131.     else
    ' B. v6 _, Z9 n- F$ \5 p; q
  132.     {
    ; {; W! _% a' g' U* q
  133.       /* Prepare Out endpoint to receive next packet */
    5 d: ]  |" u1 T8 @+ [
  134.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,6 ]! I4 s3 W. W  w* i
  135.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    * r8 e! N3 e& X/ w2 k' p

  136. 9 \. v: G, b) g9 K/ |6 ~! c
  137.                                    /* Prepare Out endpoint to receive next packet */: U  }+ d4 I2 B) m% s. `: [+ L
  138.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP1, hcdc->RxBuffer,
    % \& \- E5 A, [/ N. T/ |8 F7 M
  139.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    ' b8 t- _! \5 n( R7 F2 }

  140. $ |* l8 V% {' {+ N
  141.                                    /* Prepare Out endpoint to receive next packet */
    $ u, e0 M4 I; Z; j! Q% g
  142.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP2, hcdc->RxBuffer,* W2 E: s8 O5 R; f- w
  143.                              CDC_DATA_FS_OUT_PACKET_SIZE);' f* |* l; i) O5 P% h9 G3 t* x$ H

  144. , }$ A* ?* d5 T3 V* G
  145.                                    /* Prepare Out endpoint to receive next packet */
    + A, V; q' y- c
  146.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP3, hcdc->RxBuffer,  ?: W& N, Z1 O- f  c; _% Q' m/ G" Y
  147.                              CDC_DATA_FS_OUT_PACKET_SIZE);. {3 b$ s; n1 v# e1 x$ n

  148. . s# V, J3 W5 ?$ V  _# {
  149.                                                              /* Prepare Out endpoint to receive next packet */9 z- ^4 B+ W9 X+ I0 i& d
  150.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP4, hcdc->RxBuffer,
    & l, e' p9 R# V1 }2 V
  151.                              CDC_DATA_FS_OUT_PACKET_SIZE);. L) w) H- u' A/ n) O4 [

  152. & a+ t) a% S6 K: A2 ?
  153.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP5, hcdc->RxBuffer,/ P9 C* R4 O; @5 v
  154.                             CDC_DATA_FS_OUT_PACKET_SIZE);
    " {/ h, s; P- W8 t% `
  155.     }4 j: @2 Y1 A2 W# {% T, z( @8 \
  156.   }: F# p7 S" B- U: O8 O) x
  157.   return ret;1 M, l& R- v* m5 D/ p
  158. }
复制代码
2 n9 j6 t0 u9 ?$ s" q

1 U, [1 Y$ |0 ~3 A) q8 n' {: \+ J& P+ M5.修改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)
    - m) E! L* i* Q$ X: v6 z5 U

  • 先说说这几个函数的关系:CDC_Transmit_FS---调用--->USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
  • USBD_CDC_DataOut(数据接收回调)---调用--->CDC_Receive_FS: G, `9 d( m6 b0 s+ r5 j  M

CDC_Receive_FS(uint8_t *Buf, uint32_t *Len)修改为CDC_Receive_FS(uint8_t* Buf, uint32_t *Len,uint8_t epnum): 此后所有OUT端点来的数据都将进入此函数,可通过参数epnum区分

7 I) |- ^/ Z0 d! o7 u' ?
  1. static uint8_t  USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
    ; j: W( ^% ^) C) W) z
  2. {
    2 P# F. X: x5 w
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;2 V& E" e7 E" S3 [7 ~( @

  4. + V! F$ Z' |+ c* G6 e7 ^
  5.   /* Get the received data length */
    , V; s+ y& c* _: W6 L+ |
  6.   hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);# [8 ~7 @: X7 h
  7.   /* USB data will be immediately processed, this allow next USB traffic being
    : G" C. F0 g2 y0 s* Y2 t& {
  8.   NAKed till the end of the application Xfer */# x, C2 v9 d3 c: t/ n' ^
  9.   // printf("USBD_CDC_DataOut.1294:Len:%d :EP:%02X\n",hcdc->RxLength,epnum);
    , b1 Z* U9 T" U, i: g
  10.   if (pdev->pClassData != NULL)8 m' }2 t; s; m3 m& M2 u' k: Q
  11.   {
    ) C! F, d" m8 E7 l- M3 O
  12.     ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength,epnum);//此处修改,加入端点,相关的函数声明也跟这这样改9 A# g# G7 g' I. Y& u! o6 M
  13.     return USBD_OK;, j- b2 f5 }2 l+ M* Q  G
  14.   }
    3 p+ v! K+ O. g7 y1 ?
  15. 2 x( l% ]$ v4 J* E$ O
  16.   else( A0 ?1 Z4 m! |
  17.   {
    . \4 b# d2 e, C2 P1 K1 D4 A
  18.     return USBD_FAIL;; ]) M( T7 }2 {+ I5 H
  19.   }8 o0 T/ ~  A4 X# w# j' n7 ^
  20. }
复制代码
; t/ D. Z  g. ~! D  z- z

  • CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)该为CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum):只是增加一个参数,函数体不用动
    9 r- s9 B4 ?1 Q* j6 [/ r" o& k
$ i% g+ A8 k( d* `/ a" E

; t- }" ?2 m" ]! m; A. ?
  1. uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum)1 ^# [  c1 ~' r2 f5 z0 v
  2. {
    9 v9 ]; ]1 v9 M; W" r9 ^, D* [! n
  3.   uint8_t result = USBD_OK;
    - e; T) s: C; J. V. E& ]- V
  4.   /* USER CODE BEGIN 7 */8 q9 T% g2 [" n$ |
  5.   USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS_CDC.pClassData;
    8 G4 C; |$ J+ T$ U4 b! C
  6.   if (hcdc->TxState != 0){
      G6 P3 D, V" U5 \7 e3 b
  7.     return USBD_BUSY;
    / l5 c) S! A$ |4 ]5 |/ g2 ~
  8.   }2 H0 `7 V+ b3 w+ O1 \2 a
  9.   USBD_CDC_SetTxBuffer(&hUsbDeviceFS_CDC, Buf, Len);
    6 A* X# t' y$ `5 X1 V% f3 B  E, Z
  10.   result = USBD_CDC_TransmitPacket(&hUsbDeviceFS_CDC,epnum);    //将epnum的端点传到这个函数,这个函数也需要改
    ! b- x% l2 @3 H  U! T
  11.   /* USER CODE END 7 */3 i# }) t& z9 x, t3 x) C
  12.   return result;" a2 E! Y" n. K7 `, }- c
  13. }
复制代码
" G# ]* x5 `" o
& A* j% L  \" g" G5 `
  • USBD_CDC_TransmitPacket的修改# k- T8 w0 S; w+ H+ c2 a/ R8 T
  1. uint8_t  USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev,uint8_t epnum)) A. E, U; w( u  [  k3 u. S5 }
  2. {
    4 L" E" w. g  r+ R3 P2 s8 S
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;+ R( c- V6 U" e" M+ }9 c- F

  4. * y' A+ _- m( h
  5.   if (pdev->pClassData != NULL)/ `% Z8 M: l. S, [" [) ?- ]
  6.   {- T% S( E0 a" F9 O5 N' m7 l
  7.     if (hcdc->TxState == 0U)
    4 Z& q$ `/ D6 R7 S( Y
  8.     {/ z+ U! _3 d4 J1 B3 m+ N
  9.       /* Tx Transfer in progress *// L; G/ n8 s  p+ ?3 w
  10.       hcdc->TxState = 1U;9 B0 f7 \- y! |: C3 L

  11. + N: T. B* X2 P  F& i0 o
  12.       /* Update the packet total length */# `5 u6 r* t* y5 U& v
  13.       pdev->ep_in[epnum & 0xFU].total_length = hcdc->TxLength;//将原本的CDC_IN_EP更改为我们传入的端点
    ; k* l4 I# s/ y6 x* V3 W9 J; e; _$ ]$ _
  14.       /* Transmit next packet */7 q/ A" {# f$ I& ~6 F" v+ ~9 D$ O
  15.       USBD_LL_Transmit(pdev, epnum, hcdc->TxBuffer,( y* y% @) \0 E. X9 j" {; x# _# @0 G( Q
  16.                        (uint16_t)hcdc->TxLength);//此处也是$ t! F5 ^0 u2 l' a) v+ M

  17. : b. ^( S" ?6 a- a; h4 ]4 O
  18.       return USBD_OK;
    $ u$ ]& j# i, ~* A6 v
  19.     }
    4 ^8 `# x$ d6 h7 E' j4 n- l- v! G
  20.     else6 x1 r4 d) P! c2 C# {( u- n4 l
  21.     {
    , L' ^' O: S, w0 N1 x! ~
  22.       return USBD_BUSY;! d# Y6 ~; v3 _( K* z
  23.     }
    $ R1 T$ K' d5 t0 ]6 H% M4 K
  24.   }/ M, d4 w% x+ X2 E; M( \$ o
  25.   else
    1 ^$ @# a' X$ c1 u
  26.   {
    2 f9 e$ K2 s. W3 @
  27.     return USBD_FAIL;
    1 n. E/ }1 D  x% x, X0 f( @
  28.   }
    0 C4 k) M1 P: A; H; Q7 ?& ^6 M
  29. }
复制代码

& I1 x; d2 d1 d
& z2 N) _5 G  |2 h1 y" o6 H; q( l) t
该函数的作用:当端口接收一包数据后,需要执行此函数来接收下一包数据,简单的说:告诉主机我可以接收下一包数据了

) N; }$ @: w! s2 q# K- E+ L
  1. uint8_t  USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev,uint8_t epnum)
      v1 |& f3 y% E0 K; U
  2. {
    + l3 |  E  M  Z0 |
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;+ G' ~6 }+ b$ ^4 y! f4 Y
  4. . q0 U* l! H5 R2 B& _  a* B
  5.   /* Suspend or Resume USB Out process */+ t. f( z8 n0 m) P# G9 y2 g
  6.   if (pdev->pClassData != NULL)
      C# \$ k  [7 M
  7.   {
    5 B0 N8 n2 t9 L, k& L
  8.     if (pdev->dev_speed == USBD_SPEED_HIGH)
    7 Y) N( \, R: I
  9.     {' z5 D  n1 [5 p& m3 j8 ^
  10.       /* Prepare Out endpoint to receive next packet */0 i; ]1 H' R- N+ p1 `
  11.       USBD_LL_PrepareReceive(pdev,6 d; W# W. g* k4 `
  12.                              CDC_OUT_EP,
    # \$ i, \- v  K- t" b3 I4 {2 O
  13.                              hcdc->RxBuffer,
    5 @- J% r6 x8 T0 X9 O+ S! |
  14.                              CDC_DATA_HS_OUT_PACKET_SIZE);
    ( V0 ^0 M2 r1 ^
  15.     }
    % o  y, ]9 U- v: M+ @. f
  16.     else
    + {7 l: d8 m& [4 f% ~6 Y$ e5 v
  17.     {
    9 T( O; m2 P# a" ]. S: Z
  18.       /* Prepare Out endpoint to receive next packet */
    ; h0 h6 P+ W( ~! x3 t
  19.       USBD_LL_PrepareReceive(pdev,1 W4 f7 a* N: B4 j
  20.                              epnum,
    8 v; z$ a- ]) g: h
  21.                              hcdc->RxBuffer,- l3 l: P6 V5 B* e) u% s
  22.                              CDC_DATA_FS_OUT_PACKET_SIZE);  m& C$ A$ I! t6 W
  23.     }
    . c  M6 ?" i. {
  24.     return USBD_OK;; I% |. j- p( {+ _& n6 K
  25.   }
    2 i/ [' f, O2 ~9 R  Y4 `- M8 i
  26.   else
    ; [0 g9 C. L% }0 `7 F$ q
  27.   {& {3 X4 M0 u: Y0 A4 B
  28.     return USBD_FAIL;9 q# L, M, a2 P7 B" x8 N, P
  29.   }
    ' c* d  `5 r3 o& F) f
  30. }
复制代码

7 C- E9 x% X1 \( N, y  b" U
对以后而言,我们就使用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了

5 n% C8 G; l; h  P0 }
6.后续
  • 此时就完成了,不过不排除有些深层的问题。
  • 如:当五个CDC同时在Read时,其中一个close,有可能会导致其他四个都无法再Read出数据,需要重新Open,但在电脑的深度depin系统上并没有这个问题,在项目中的板子上就有,希望大佬们提供下线索。感激不尽
      ^$ C) ^9 v, e( I/ q# F

& c. V7 N( c. e& D+ M9 {  N6 s1 w2 S9 O9 M7 m8 c- \& H
转载自:casojie( M" C6 [7 @( k, w5 G8 e" E) `  u
赞 收藏 评论0 发布时间:2023-1-3 19:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版