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

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

[复制链接]
STMCU小助手 发布时间:2023-1-3 19:55
1. 背景
  • 由于项需求,在STM32F072中需实现5个CDC设备,折腾了很久分享出来,希望能帮助别人少踩一些坑.USB2.0全速,该款单片机支持8个输出和8个输入端点
  • * G% k* l5 S2 Q: o
2.1 它是什么?需要使用到什么?
  • 它是USB设备类型的一种,如U盘插入电脑时,电脑会知道其是U盘,是一个存储设备,那么它就属于USB MCU存储设备。USB协议中对设备进行了分类.它在stm32上叫虚拟串口设备,当将其链接电脑后,可以把它当成串口使用,如使用windows的串口工具打开它,设置波特率等等,这是我的理解。
    4 @6 _5 e! C! L; K' L$ _: `
+ {  q* N# y8 b* T$ m
  • 它需要两个接口,三个端点
    ! x4 U  p1 h5 [) S& a2 N
7 z+ [% p* @" w! s1 ~
  • 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都是相对于主机而言! s& p1 M; `  }6 O4 P3 X
  • 由此可见,正常情况下,一个CDC需要三个端点,其中两个IN端点,一个OUT端点( n* x' j6 {! e7 }! y8 q5 a

    4 s$ a$ z+ Y6 i3 m9 G
3.配置过程3.1 配置流程
  • 在STM32CubeIDE的帮助下,生成一个CDC的代码,这里没什么坑,点几下就成功了,注意的是可能需要将Heap设置大一点
  • 修改设备描述符
  • 分配端点和修改配置描述符
  • 分配PMA端点缓存地址
  • 修改HAL库关于CDC部分函数接口的参数,以适配多CDC设备的情况
    - _7 P3 r# w! e- W' e& ~0 q
& v7 C: l3 a. U! j) [$ H7 x
. h" a4 x3 ~7 Y; E  t
3.2 使用STM32CubeIDE生成一个CDC程序的代码
  • 根据下面的文件操作即可,文件会介绍USBCDC的知识,在PDF的最后会说怎么使用cubeIDE配置,很简单没什么坑(注意的是可能需要将Heap设置大一点)
    4 y2 A) ~8 V, X( y( a6 N9 Y

, \) V2 t* |) {; ]
7 X. C0 f% {# i3 U0 ~
3.3 分配端点和修改配置描述符
  • 此时问题来了,CDC要求3个端点,其中2个输入1个输出,而stm32F072只支持8个输入端点,8个输出端点,2x5>8,正常情况下是不够的,这里就需要将IN端口中的控制端口省略,也就是第一幅图中的Interface 0中的endpoint IN端点,不分配有效端点给它,在本款单片机中IN端点的有效范围(0x80-0x87),OUT(0x00-0x08); T% G+ F6 T; p
. _, x1 _% [& |5 Z: S" j
& W; i4 x- V, }% v/ F5 m$ K
  1. #define CDC_IN_EP                                   0x81U  /* CDC*/( y8 D. N8 S0 u+ U$ i( T
  2. #define CDC_OUT_EP                                  0x01U  . ?- S  J; D1 z# m
  3. #define CDC_CMD_EP                                  0x88U  //无效端点
    ' f: F0 L- O' L! w: |
  4. : ^7 p- y7 u$ k
  5. #define CDC_IN_EP1                                   0x82U   /* CDC1*/
    ! ^/ \; L% p1 ~
  6. #define CDC_OUT_EP1                                  0x02U  ) j* H, E( w* Q9 H% I4 J! i8 a
  7. #define CDC_CMD_EP1                                  0x89U  //无效端点
    & g0 ]6 t9 q0 S% W3 ]3 j- ~
  8. & q7 `$ g4 V, M! B1 B
  9. #define CDC_IN_EP2                                   0x83U   /* CDC2*/$ L3 b( U/ Z6 G3 x2 S! j
  10. #define CDC_OUT_EP2                                  0x03U  
    ; `! [& [7 V: f" M+ ]  M
  11. #define CDC_CMD_EP2                                  0x8AU  //无效端点
    1 `! \0 ~4 W; L* M0 G# d
  12. # w1 v+ q2 p1 H: f9 ?+ s+ l
  13. #define CDC_IN_EP3                                   0x84U   /* CDC3*/1 U5 B. ?8 y/ Y$ L8 i3 }- z/ x9 m6 L
  14. #define CDC_OUT_EP3                                  0x04U  
    + }  O! X* y9 F! j% _/ s1 z
  15. #define CDC_CMD_EP3                                  0x8CU  //无效端点' _; ~. t5 p4 q9 ~& v
  16. ) F( Y* `, N' w* R5 o$ G: N
  17. #define CDC_IN_EP4                                   0x85U   /* CDC4*/
    . H; }1 W* T! b) {" T; h6 ~
  18. #define CDC_OUT_EP4                                  0x05U
    6 u. Z+ z0 b$ M
  19. #define CDC_CMD_EP4                                  0x8BU  //无效端点
复制代码
% I5 n- J$ `7 j: U  ^
- r7 q# z+ K5 f- F( n+ g6 n
  • 修改配置描述符号,这里面的内容就很多了,里面涉及到USB方方面面的属性和参数,其中USB_CDC_CONFIG_DESC_SIZ是该结构体的大小,记得修改,或者直接改为最大255。8 d% f( ~. X7 ]0 o4 J
  • 配置描述符的结构如下:
    % }' S- E: b0 c$ E/ K0 f
    - `: {1 ^, H2 ~& O% L: i$ c9 P
  1. 配置描述符
    * \$ q! A$ S' \+ M: p
  2. {
    % g) _& o" W% u- w( Y3 @
  3.     配置描述符总概括(相当于预览:9字节)
    , p9 t6 [) n3 H" e7 H3 L) _
  4.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC1 C( {" b( t# V  S2 I- B9 l
  5.     {
    . m6 D$ c" j. p/ b3 x
  6.         接口描述符1
    " V+ ?' v. r) x6 `  b. h  @
  7.         {+ Y; `" t/ f; G4 b, H  J  D
  8.             其他描述符(ACM等)9 t1 N% f& w7 d5 L8 E
  9.             端点描述符(控制端点)) a6 G& _& _: G2 P1 A3 V
  10.         }! u5 K; A3 H0 @3 J7 X* B+ f
  11.         接口描述符2
    8 |! O: `4 l6 ~) c2 l$ b
  12.         {" F; k( w3 a' S
  13.             端点描述符(IN)$ C) i9 }6 f; a) D9 j% K* d
  14.             端点描述符(OUT)1 n; B" F, e  a) |" f. Y4 F) ~
  15.         }( B$ n; |. E0 n* N! L0 H* [
  16.     }
    / W% \  q4 K' v

  17. * q, d8 O) v/ h% e
  18.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC1
    , _0 ]  A; d8 @
  19.     {
    , L3 k/ m5 T; B- k! a! ]/ v; N
  20.         接口描述符1
    7 Z7 P5 U# q& q1 h
  21.         {
    4 U) s/ h. A9 @; |
  22.             其他描述符(ACM等)
    & o; M3 M4 y# u" Y
  23.             端点描述符(控制端点)
      f' s: X( P* A  T* M8 a0 w7 g
  24.         }5 x  X8 }  V9 `* D4 i; l% [' w
  25.         接口描述符2
    - b  h3 {3 s) B
  26.         {' ]4 |! ]( J4 B7 @0 D5 `% H
  27.             端点描述符(IN)  s0 I- ?" S) J
  28.             端点描述符(OUT)
    8 f! U3 V% s/ M0 p5 u1 D
  29.         }
    # e- ^$ j( ?* W& y+ P  C0 o
  30.     }% H6 B7 L0 S" f) a% `' g- u

  31.   o4 H, x0 Z7 K2 o% n. q' [5 ^
  32.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC2
    # g2 R+ S' ~/ [( Y
  33.     {" c/ L( L) [9 u! O) v6 K9 @1 P
  34.         接口描述符1
    % u1 W( h% Z4 ^2 X" t: O
  35.         {/ C4 I5 N; A8 G% }& b: U
  36.             其他描述符(ACM等)
    ) r! j/ B8 C6 k, y* u# @. V
  37.             端点描述符(控制端点)
    ) q; x) t2 Q7 X: s
  38.         }4 o, o, Y, L. I# r: o
  39.         接口描述符2
    0 N$ Q5 a# N# m
  40.         {+ y- m3 \& Y5 Q: O7 S: t
  41.             端点描述符(IN)
    $ e- Z* C$ o! R9 I4 M
  42.             端点描述符(OUT)  B/ f1 l# q* y2 k
  43.         }3 r$ v; h, M0 L/ E% e
  44.     }) R& |- I# W/ ]. s

  45. ! H; N7 k& ~7 L
  46.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC38 w. w6 b+ ^3 F+ B$ e3 ]5 `! E
  47.     {( T" Z9 K% d; W1 e: T
  48.         接口描述符1$ Q: g* r+ D2 V* E
  49.         {/ q5 q, n6 y& ~) o3 K3 `! Q
  50.             其他描述符(ACM等)4 g: U0 K$ M5 v' D4 \3 V) `
  51.             端点描述符(控制端点)% g' t2 V; B2 N5 l0 q  n
  52.         }# v2 l2 u  a; j
  53.         接口描述符2
    " j9 N- C3 X) a% B  l
  54.         {* c6 ?) O* r  y$ T5 h8 }
  55.             端点描述符(IN)( w6 P1 e- l) K1 ?, A' ^
  56.             端点描述符(OUT)
    % E, S* o' [. e' J
  57.         }
    : W8 c( F0 Y, u4 B) Z
  58.     }
    4 w2 N- G+ R6 p) g! c+ u% X( b

  59. & L' l' v0 t8 Q5 T7 o9 ^
  60.     IAD描述符(标识接下来的接口属于一个设备,一个设备就一个IAD描述符)CDC48 t$ ~+ p7 F1 w7 Z
  61.     {
    ; d# t# W0 [7 D( S$ t* I: r! K
  62.         接口描述符14 V2 z% N9 G0 z  ]/ F
  63.         {
    0 k. \3 ^% t; b) A/ J' p
  64.             其他描述符(ACM等)
    & Z- b5 W, {) D% d" V/ U# v0 ]
  65.             端点描述符(控制端点)+ {" B* p( w  V$ \* K  z; w8 l
  66.         }$ J0 z( E1 P# N3 G% A, w# R, `
  67.         接口描述符2
    6 X" _7 o. t4 B9 l. Z: t6 t
  68.         {" j& D3 I. ?+ j
  69.             端点描述符(IN)' r# d0 X  s0 [# `' v  f
  70.             端点描述符(OUT)
    # M2 g" J3 q0 Y4 \
  71.         }
    ( H, `' `+ B' y# w
  72.     }) x8 v* X' k9 d
  73. }
复制代码
& h0 z" B6 x7 Q" T' E9 M; s
  • 配置描述符如下,下面有些字段需要修改的,都用casojie标记了,CTRL+F搜索casojie就可以方便显示;
    * o( E3 \3 g0 v

" g: [2 I: [$ j' m0 Q0 ^' @$ P2 j
$ `" j$ |6 }' }0 w0 A% @3 M
  1. __ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =6 @, ~, }! {3 g0 B
  2. {; O. U% J. ^: B2 W/ p1 Q$ I. ]
  3.   /*Configuration Descriptor*/8 C3 _2 H' T8 K- p* D* k
  4.   0x09,   /* bLength: Configuration Descriptor size */
    5 w+ \$ q) v" m4 Z
  5.   USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration */9 ?+ g# z1 B1 L/ h+ X# X
  6.   USB_CDC_CONFIG_DESC_SIZ,                /* wTotalLength:no of returned bytes */
    % D; q  p0 _$ [- t
  7.   0x00,
    ! {( v/ t6 m! x, a7 ?3 a
  8.   0x0A,   /* bNumInterfaces: 10 interface *///总接口大小,5个CDC*2=10=0x0A casojie/ M0 {7 J: Q$ T$ X$ ?: z
  9.   0x01,   /* bConfigurationValue: Configuration value */5 g0 f1 D- a1 G  `: o
  10.   0x00,   /* iConfiguration: Index of string descriptor describing the configuration */4 H/ v# L0 |0 Z$ }! r
  11.   0xC0,   /* bmAttributes: self powered */
    + y* ]" a; k0 a' t4 @/ O/ p# Z
  12.   0x32,   /* MaxPower 0 mA */
    * ?2 o3 G: D& D# f- s0 z  q$ U
  13. ( Z. G, {9 L$ O# R/ h
  14.   /*------------------------CDC0--------------------------------------------------8+9+5+5+7+9+7+7-*/; F: ^. s, l3 I3 N. ^0 t% C8 ?! K( e/ _
  15.   // // // IAD  Interface Association Descriptor //IAD描述符需要添加 casojie- ^6 G* X, {/ U! @0 F" O
  16.   // 0x08,  // bLength: Interface Descriptor size //标识IAD描述符的长度,基本都是8,casojie
    1 S6 D. a- h1 k/ |6 O* r8 M/ ?
  17.   // 0x0B,      // bDescriptorType: IAD            //不用管6 J* W* V! @% a; t# l0 c
  18.   // 0x00,  // bFirstInterface                      //第一个接口的序号9 ?1 Q* b# w. v9 M6 p, G
  19.   // 0x02,  // bInterfaceCount                      //本IDA的接口数量
    0 [3 l7 k( S( l
  20.   // 0x02,  // bFunctionClass: CDC                  //表明该IAD是一个CDC设备- r# _4 L7 ?3 h8 Q2 [& [5 F+ Z: J
  21.   // 0x02,  // bFunctionSubClass                    //不用管+ c- {& O3 D# Z
  22.   // 0x01,  // bFunctionProtocol                    //控制协议等其他我也不懂,默认就行; Z+ }; ?, A6 A. d2 g, H0 N
  23.   // 0x02,  // iFunction    - a4 }" S3 x) v0 i; |7 r1 n! j9 [
  24. . e" m$ }# L; Q% o, M
  25. /*Interface Descriptor */
    3 M+ r0 `5 C* h
  26.   0x09,   /* bLength: Interface Descriptor size */
    - d/ D* c9 G( L7 ]; ^( x3 X/ ^
  27.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */( @* h# B- K: k6 l
  28.   /* Interface descriptor type */
    8 N0 `3 R$ j  @) l) P
  29.   0x00,   /* bInterfaceNumber: Number of Interface */   //接口编号,从0开始 casojie0 L% s6 h( t  D
  30.   0x00,   /* bAlternateSetting: Alternate setting */; K2 X( F: Q6 r" P  P! [% N* C
  31.   0x01,   /* bNumEndpoints: One endpoints used */       //接口内有多少个端点被使用 1个 casojie( ?; u, f: a& q% f4 a9 q
  32.   0x02,   /* bInterfaceClass: Communication Interface Class */
    / X+ C$ K8 B! ]' O# t: t0 h
  33.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    , D7 T; _2 L, H4 u& D8 x
  34.   0x01,   /* bInterfaceProtocol: Common AT commands */
    ) I) ~5 d, d2 p
  35.   0x00,   /* iInterface: *// c" |( t6 I" L8 L' [  V4 }& {
  36.   G* O7 s2 z+ k( h
  37.   // /*Header Functional Descriptor*/& }  B/ o1 b- i' j5 c7 O" s
  38.   // 0x05,   /* bLength: Endpoint Descriptor size */
    ! U7 P" C( @5 H8 L4 p
  39.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
    ( f1 z; ?, M+ h; k5 N
  40.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */5 T* k  @4 m! {* {
  41.   // 0x10,   /* bcdCDC: spec release number */& e5 Q5 }" _) q8 I; R( f9 J% \
  42.   // 0x01,, j; {& {6 ?) U7 k2 y) X" |
  43. * B6 f2 s# Z* E* Z4 F1 g
  44.   // /*Call Management Functional Descriptor*/
    ; C, |9 Q; V. h- k% M9 H( [% j
  45.   // 0x05,   /* bFunctionLength */5 E2 C# J, H: J+ j
  46.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
    5 a& `1 g+ V, H3 L' R
  47.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */! P# W0 [6 S' Z- V5 \
  48.   // 0x00,   /* bmCapabilities: D0+D1 */
    - l- T* r! p+ H& k$ ~- }/ ^
  49.   // 0x01,   /* bDataInterface: 1 */
    - C5 J1 I' v" w3 Q$ E9 K3 Q% _8 [
  50. ) a8 h5 e) T$ L; k* N9 M/ w/ m; Z! t
  51.   /*ACM Functional Descriptor*/
    1 Y7 P, v8 |! Q: y
  52.   0x04,   /* bFunctionLength */& O- G2 q3 g$ J$ T
  53.   0x24,   /* bDescriptorType: CS_INTERFACE */2 T  F8 C* m# n9 f# _
  54.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    & g1 S( w; R, P4 I
  55.   0x0F,   /* bmCapabilities */
    7 t# X: H% D7 \! r4 M5 {% x

  56. 6 `2 S, @$ h' u5 j- B3 I; i
  57.   /*Union Functional Descriptor*/
    3 H% k! `" D) S3 v% v
  58.   0x05,   /* bFunctionLength */
    / Y, E/ S: Z9 k6 S$ K: o
  59.   0x24,   /* bDescriptorType: CS_INTERFACE */4 T$ R6 p! B% L' x
  60.   0x06,   /* bDescriptorSubtype: Union func desc */
    : e! O0 v9 b4 Y' P( F9 b1 j3 ]
  61.   0x00,   /* bMasterInterface: Communication class interface */ //联合描述符,与IAD功能类似,标识哪两个接口是属于一个设备的casojie
    ) l9 {# D  ?8 `$ T
  62.   0x01,   /* bSlaveInterface0: Data Class Interface */  //与上面一样,上面是0,这里是1,标识0号,1号接口是属于一个CDC设备的 casojie
    5 y3 g- h; h' i; q( {" ?2 u
  63. ) E' R% `  k8 o3 Z' m1 w
  64.   /*Endpoint 2 Descriptor*/2 f6 L% ~- S$ h& o
  65.   0x07,                           /* bLength: Endpoint Descriptor size *///控制端点描述符,虽然端点号是无效的,但是这个描述符不可省略5 s  s  m, x1 c; B7 j; v
  66.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    ( r0 F; [- H( V* S
  67.   CDC_CMD_EP,                     /* bEndpointAddress */! R6 ?' C- Z+ d6 g
  68.   0x03,                           /* bmAttributes: Interrupt */
    5 {0 x2 A! \% Q5 V
  69.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    2 G4 t! I/ m- Z8 L
  70.   HIBYTE(CDC_CMD_PACKET_SIZE),4 \( f( M; _. z; B8 L5 q8 z" g3 @
  71.   0x10,                           /* bInterval: */ , w7 j% s2 o9 G3 `9 ]
  72.   /*---------------------------------------------------------------------------*/1 a, s8 g) G, e  B9 \2 B
  73. 9 ^  U1 e/ X4 U" O  v: \3 u
  74.   /*Data class interface descriptor*/   //第二个接口描述符 casojie
    5 f% Z9 w" r& V3 r
  75.   0x09,   /* bLength: Endpoint Descriptor size */0 T2 D* t3 q: d2 f
  76.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */; y) _- q2 T2 d* J
  77.   0x01,   /* bInterfaceNumber: Number of Interface */   //接口的序号,上一个接口是0,那这里就是1 casojie" G2 ^2 N: x; ]( ~, ]# X7 e
  78.   0x00,   /* bAlternateSetting: Alternate setting */
    6 i" g; f8 {; q# \* ]6 t
  79.   0x02,   /* bNumEndpoints: Two endpoints used */       //标识此接口有两个端点(IN)(OUT) casojie
    7 |$ F# z! M* z$ R- R& ~' J
  80.   0x0A,   /* bInterfaceClass: CDC */
    4 n, Z) b4 R. s) w# S  C6 {+ Q
  81.   0x00,   /* bInterfaceSubClass: */
    & j4 A8 b( }/ G  f5 y
  82.   0x00,   /* bInterfaceProtocol: */
    ; b2 s  w( {2 x/ s1 Q" z
  83.   0x00,   /* iInterface: */
    ' m4 c& ~% @2 H4 t

  84. 9 B0 l0 m! x+ J9 h$ @
  85.   /*Endpoint OUT Descriptor*/                       //OUT端点" A# N( a& S% \* |( y3 ?; x
  86.   0x07,   /* bLength: Endpoint Descriptor size */$ p) h- d/ [# W. I2 L4 P
  87.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    , o5 x+ b% N  N) o* ?* p% r
  88.   CDC_OUT_EP,                        /* bEndpointAddress */8 |+ j7 Y5 E  M- e* @! y4 R
  89.   0x02,                              /* bmAttributes: Bulk */
    7 G- S; p  `. |: _1 h
  90.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    3 w' m$ q9 k- ?  F9 Y7 i! D
  91.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE)," }, x6 _5 `2 ?. x' U
  92.   0x00,                              /* bInterval: ignore for Bulk transfer */& @$ O8 U3 e: Y7 H# c% X9 f. I6 q9 o
  93. . t! M! }9 e% _' S6 M) @! g
  94.   /*Endpoint IN Descriptor*/                        //IN端点$ c4 A9 @# v/ y0 {+ R
  95.   0x07,   /* bLength: Endpoint Descriptor size */
    2 P+ R! R$ S3 w* v" ]
  96.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    4 Q7 R8 p9 D0 n4 a+ W* O  y
  97.   CDC_IN_EP,                         /* bEndpointAddress */5 m$ }5 |' ^, v
  98.   0x02,                              /* bmAttributes: Bulk */
    ; y# e$ [: b# V' U! ^% J9 n
  99.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */: a. ~& n* J( F6 C2 D
  100.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),1 t6 I8 g7 m7 o  E
  101.   0x00,                               /* bInterval: ignore for Bulk transfer */
    ) q4 l4 D# C! K' z) C; F2 r
  102. 6 f' h* }  l: B' h! p
  103.   /*---------------------------------------------------------------------------*/
    8 {* n- Q. H3 a6 G
  104.   // IAD  Interface Association Descriptor       //这里就是CDC1了,重复CDC0的配置过程,注意有些字段的序号 casojie$ p' m, O  |; Z& y- W. {4 h" u: Z* @
  105.   // 0x08,  // bLength: Interface Descriptor size
    1 J. I' \, I0 ?, K& H" Z! E- v
  106.   // 0x0B,      // bDescriptorType: IAD* l( f+ Y% z) s# k" j9 p
  107.   // 0x02,  // bFirstInterface                  //太多了,写不下去了,意思和第一个IDA一样的
    9 m: |- e7 c; p; t0 Z1 u3 d: S
  108.   // 0x02,  // bInterfaceCount
    ' E# e  G+ H9 H( i4 Y0 H
  109.   // 0x02,  // bFunctionClass: CDC$ t, e3 V+ M: c3 ~: V$ k6 G
  110.   // 0x02,  // bFunctionSubClass6 v9 m% _* Y. r
  111.   // 0x01,  // bFunctionProtocol : S& D) W' D! u; |# K
  112.   // 0x02,  // iFunction+ v0 S# q- B. d) \/ k

  113. 4 @0 H; \# R2 z' r
  114. /*Interface Descriptor */. O! p/ H  r/ P/ i5 g* Z  q9 U8 ]
  115.   0x09,   /* bLength: Interface Descriptor size */
    4 k  k) k0 G( X4 F2 h  L) c
  116.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */' s6 r3 p* y9 M8 w" |* i
  117.   /* Interface descriptor type */
    ( t% p. Y; L* |
  118.   0x02,   /* bInterfaceNumber: Number of Interface */
    $ Y+ K' E; k& S5 `8 U
  119.   0x00,   /* bAlternateSetting: Alternate setting */
    + i4 A% F, L+ V8 o
  120.   0x01,   /* bNumEndpoints: One endpoints used */
    ; }+ Q& s: V: c- K% L) V! R
  121.   0x02,   /* bInterfaceClass: Communication Interface Class */
    ( n' ~; w' P6 [
  122.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    & m& u4 k, e6 n) V3 _8 X
  123.   0x01,   /* bInterfaceProtocol: Common AT commands */
    0 a+ [$ `( i" R
  124.   0x00,   /* iInterface: */
    - o+ ?' {' a2 G0 Z& ]6 J1 Y7 N

  125. + n! I  D6 M/ |
  126.   // /*Header Functional Descriptor*/
    ; q/ L2 `4 o7 i9 j9 y# j
  127.   // 0x05,   /* bLength: Endpoint Descriptor size */) Q/ a% ?7 z( f( R5 Y4 A
  128.   // 0x24,   /* bDescriptorType: CS_INTERFACE *// _( |% D6 N+ P
  129.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */
    8 l+ s( \8 {7 ?4 Y+ d& u, ?% r
  130.   // 0x10,   /* bcdCDC: spec release number */
    9 X9 I+ `( Q& T
  131.   // 0x01,
    , s" y% i2 T5 j: t% H, x
  132. 3 U0 E/ o1 g/ G0 z
  133.   // /*Call Management Functional Descriptor*/2 ?5 o  p% \+ E8 ?- b3 \
  134.   // 0x05,   /* bFunctionLength */
    2 E6 U* V) d' ^/ z  ^2 k7 h
  135.   // 0x24,   /* bDescriptorType: CS_INTERFACE */' f8 m( e5 J7 m, \
  136.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */
    * E& I: f5 u% o. ?% W+ ?9 i, j
  137.   // 0x00,   /* bmCapabilities: D0+D1 */
    8 h( ^- h5 |) U0 G) v) _
  138.   // 0x01,   /* bDataInterface: 1 */
    $ e& W9 E; {0 ]7 v- X' c2 W

  139. : i$ q! S& r' v6 P# `
  140.   /*ACM Functional Descriptor*/' H! V9 W; P4 q2 g5 l7 J2 M
  141.   0x04,   /* bFunctionLength */
    # f" o* k) x, J3 [
  142.   0x24,   /* bDescriptorType: CS_INTERFACE */
    + [3 P) {. t, [( ^% u! m7 \4 Z6 G
  143.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    5 F! v6 m, j. G
  144.   0x0F,   /* bmCapabilities */
    + e& g# N1 L0 [, w) G# W( S1 ^

  145. 5 \- D6 n/ H- s& B4 i2 s
  146.   /*Union Functional Descriptor*/; {8 A) b* O+ U% ~  o: I3 [
  147.   0x05,   /* bFunctionLength */" G2 J* y4 M: g+ c. E  U
  148.   0x24,   /* bDescriptorType: CS_INTERFACE */8 k0 V/ Y% a3 D/ @4 m* _: J
  149.   0x06,   /* bDescriptorSubtype: Union func desc */
    1 Q' B* A8 p1 `4 Z* }, e& {* R0 r
  150.   0x02,   /* bMasterInterface: Communication class interface */
    & b# ~4 P( ?" q( J* F+ U+ ]& l
  151.   0x03,   /* bSlaveInterface0: Data Class Interface */* o6 d/ H$ ^1 j9 q, Z# h$ J2 n1 }
  152. : _2 J0 y; f3 n5 J  F) r1 n
  153.   // /*Endpoint 2 Descriptor*/
    % f4 z, q, r. e7 p/ D8 X" c% V
  154.   0x07,                           /* bLength: Endpoint Descriptor size */8 K' ?9 ^5 [" V, X% U5 j2 T
  155.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    * R: S2 h- y8 J' T$ w4 H5 H  ^
  156.   CDC_CMD_EP1,                     /* bEndpointAddress */
    / k6 X* p! c  k. {
  157.   0x03,                           /* bmAttributes: Interrupt */' u% F# E( Z% U+ B1 W  y& V
  158.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    5 a, S4 o) H9 ~. [% e
  159.   HIBYTE(CDC_CMD_PACKET_SIZE),
    . l& g4 P1 l& ^9 t
  160.   0x10,                           /* bInterval: */
    - s! G/ x3 |9 S$ j& F" K
  161.   /*---------------------------------------------------------------------------*/" X" b2 k8 D8 Z, j4 ~4 w

  162. 2 J! G3 ~: U- R* s: b: p, f
  163.   /*Data class interface descriptor*/
      a4 C6 G0 x6 h5 z
  164.   0x09,   /* bLength: Endpoint Descriptor size */
    6 q  m" _! x  W+ P/ g
  165.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    " `0 q* A. ~# I6 B
  166.   0x03,   /* bInterfaceNumber: Number of Interface */
    $ y* O5 D$ ?; |' G
  167.   0x00,   /* bAlternateSetting: Alternate setting */1 b! R1 B# X: }* z, A! U  z
  168.   0x02,   /* bNumEndpoints: Two endpoints used */
    3 i1 L! H' z6 S) F
  169.   0x0A,   /* bInterfaceClass: CDC */3 i" x; U& `; h4 `) L
  170.   0x00,   /* bInterfaceSubClass: */
    + c0 o1 k9 y, a6 @% S  M
  171.   0x00,   /* bInterfaceProtocol: *// R$ }" L" n& d) y
  172.   0x00,   /* iInterface: */3 X/ d- C8 I" e, S7 j% O3 N& _
  173. " m8 o$ y4 u0 o. Q7 b
  174.   /*Endpoint OUT Descriptor*/4 N; }) v! D5 i1 y2 D
  175.   0x07,   /* bLength: Endpoint Descriptor size */& D3 F8 G8 p+ x% [. x' }  q* Z
  176.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */; D" q  ^8 a. Q8 W& |
  177.   CDC_OUT_EP1,                        /* bEndpointAddress */( m0 z, ]9 m& `3 T; T$ ?, M8 p8 i
  178.   0x02,                              /* bmAttributes: Bulk */( {0 c" s: g  l  i
  179.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */2 @, H! m( x+ k
  180.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    7 M- ?( ?" E5 o, i8 m4 z
  181.   0x00,                              /* bInterval: ignore for Bulk transfer */
    3 }) h, u) q& ~: I- u
  182. $ V4 P  V! y6 y  S
  183.   /*Endpoint IN Descriptor*/
    ) K4 W: T1 t6 Y: \" _( D
  184.   0x07,   /* bLength: Endpoint Descriptor size */( W  y# y& ]$ I5 [' K
  185.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */1 `/ [4 N( M6 W; y6 h- t& T
  186.   CDC_IN_EP1,                         /* bEndpointAddress */
    + \' U* B- w6 M; d2 F/ s: U: k3 E
  187.   0x02,                              /* bmAttributes: Bulk */+ z: k5 |/ r3 u8 N, m
  188.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */4 z  w$ k% a& U' r
  189.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    ( q+ X& m, k! `; \
  190.   0x00,                               /* bInterval: ignore for Bulk transfer */
    ! H' t# H7 s4 V7 e: h7 s% M, ~
  191.   /*---------------------------------------------------------------------------*/
    : P  L) R0 ^+ H% d
  192.   // IAD  Interface Association Descriptor
    2 @0 e- H3 p( F
  193.   // 0x08,  // bLength: Interface Descriptor size( ^6 b3 o: _& i
  194.   // 0x0B,      // bDescriptorType: IAD
    ' d1 \. z5 ]! R2 S6 I
  195.   // 0x04,  // bFirstInterface
    & g! A1 C$ ~) c- n9 X) [, w
  196.   // 0x02,  // bInterfaceCount8 G: O7 {; C' A3 x% f
  197.   // 0x02,  // bFunctionClass: CDC
    # _/ ^2 z, ?: V' ~) t8 r
  198.   // 0x02,  // bFunctionSubClass7 ^1 S7 i2 K4 u5 P- I! m
  199.   // 0x01,  // bFunctionProtocol $ o( x3 m+ H) X9 r
  200.   // 0x02,  // iFunction2 h1 N) W. ?6 a! ~1 |' N' E; q

  201. $ @% _: _8 T& @# Q  S+ j& u! r2 R
  202. /*Interface Descriptor */+ B, ]; D) }9 A1 g2 E/ ?
  203.   0x09,   /* bLength: Interface Descriptor size */7 ~% R  W4 J8 P" {) R
  204.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */2 }: N' L# M& z& t& \5 r
  205.   /* Interface descriptor type */
    0 B; J" W2 {2 R) E  N4 ?
  206.   0x04,   /* bInterfaceNumber: Number of Interface */
    # w# i) `" V; v
  207.   0x00,   /* bAlternateSetting: Alternate setting */9 e8 L- C6 h8 K5 O/ ^4 b
  208.   0x01,   /* bNumEndpoints: One endpoints used */
    1 B6 {6 T5 X, t6 f
  209.   0x02,   /* bInterfaceClass: Communication Interface Class */
    ) m8 N6 U2 t4 g* q- E
  210.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    ( f5 ~* Y: g5 s; R3 O; n7 N) y  |
  211.   0x01,   /* bInterfaceProtocol: Common AT commands */1 |# m% M4 f2 J
  212.   0x00,   /* iInterface: */  z4 ?5 K# z- I" ^

  213. . `7 P+ i% O& H& m9 ?
  214.   // /*Header Functional Descriptor*/0 `! _; N- K8 t+ v
  215.   // 0x05,   /* bLength: Endpoint Descriptor size */  m& M  b9 X% K: C! @% ~( v! k
  216.   // 0x24,   /* bDescriptorType: CS_INTERFACE */. L6 K8 G4 K, s0 {$ e9 j0 r$ N
  217.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */
    % `% }  N6 B9 s: i; o9 b8 q
  218.   // 0x10,   /* bcdCDC: spec release number */
    * s3 V/ o/ e9 {( x" e
  219.   // 0x01,
    7 F& s* L- n7 ~. m+ s- i& b% d
  220. " ^' {' {* H# |: D, |) u
  221.   // /*Call Management Functional Descriptor*/' |4 ]8 f- j  s  Q! D: D
  222.   // 0x05,   /* bFunctionLength */
    + l" ^0 g, c" S9 J. q7 @( u% M: q
  223.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
      f$ Q2 [, Z$ M" y
  224.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */
    ( L# T' ~- ^" z( i( i3 h- L
  225.   // 0x00,   /* bmCapabilities: D0+D1 */
    # F8 R( `; R1 [: T  u
  226.   // 0x01,   /* bDataInterface: 1 */  }4 f5 g5 d: v, Q& P

  227. $ t+ v. S' F1 @- A+ o
  228.   /*ACM Functional Descriptor*/+ B; N: x2 P1 u1 u( N" V- i
  229.   0x04,   /* bFunctionLength */8 i/ f; k4 `/ p: {  m8 Z9 ~
  230.   0x24,   /* bDescriptorType: CS_INTERFACE */
    7 X* `* b8 T$ B
  231.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    4 I& |( G# i3 D8 ?% Z( C1 t
  232.   0x0F,   /* bmCapabilities */
    7 l1 q  b/ g: d; }6 G; ~
  233. 3 ^5 V/ W% N& U  E8 B" u2 m
  234.   /*Union Functional Descriptor*/% T) o) ]# L% E) {7 m
  235.   0x05,   /* bFunctionLength */0 q/ c, |8 ?! t8 r7 k6 \6 G6 y0 C
  236.   0x24,   /* bDescriptorType: CS_INTERFACE */* N( |* f. _7 \! }  ]1 ]9 X8 U' H
  237.   0x06,   /* bDescriptorSubtype: Union func desc */" r7 d* W  d& {' d' e2 n
  238.   0x04,   /* bMasterInterface: Communication class interface */
    # ?2 W; i0 L' n, a4 a* \
  239.   0x05,   /* bSlaveInterface0: Data Class Interface */
      k: M5 T5 N8 d0 W& }
  240. 5 s; I& X/ o6 L3 a9 J
  241.   // /*Endpoint 2 Descriptor*/
      o; }% d' Z/ }; b0 q
  242.   0x07,                           /* bLength: Endpoint Descriptor size *// n! P. r) d# j3 |5 d
  243.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    % i- N) r' v( T+ S: _
  244.   CDC_CMD_EP2,                     /* bEndpointAddress */9 P+ y; o, {2 c/ ?* b8 p
  245.   0x03,                           /* bmAttributes: Interrupt */
    ) H( \* `7 t: |- V
  246.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    , l. A! G6 c! |# ?9 y  f+ f
  247.   HIBYTE(CDC_CMD_PACKET_SIZE),# A0 @# Q( b" D- H, Q
  248.   0x10,                           /* bInterval: */ 4 ~* d  ]& {* q2 v3 P- ?
  249.   /*---------------------------------------------------------------------------*/
    5 R* `0 T* Q  a* L; a4 N# G

  250.   O, I) d% L! D5 ^
  251.   /*Data class interface descriptor*/* k8 E" u0 f1 N' Q4 `7 }4 t0 T, }
  252.   0x09,   /* bLength: Endpoint Descriptor size */
    % n7 [, T0 `5 G% ~: ^( a
  253.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    : v) s* m  h6 v  ?2 e. G8 D
  254.   0x05,   /* bInterfaceNumber: Number of Interface */6 }% E, L! `. S# {$ G1 B
  255.   0x00,   /* bAlternateSetting: Alternate setting */
    3 @# d+ _9 C7 c6 `
  256.   0x02,   /* bNumEndpoints: Two endpoints used */
    ; U& N0 a+ W" U( u
  257.   0x0A,   /* bInterfaceClass: CDC */" l8 L6 ^1 |$ Y$ g( L+ b
  258.   0x00,   /* bInterfaceSubClass: */
    , U& ]  o; G+ U# z6 E( M
  259.   0x00,   /* bInterfaceProtocol: */( a6 ?) Y  q6 @; D! B6 b5 v
  260.   0x00,   /* iInterface: */
    " D! e! [: S2 d1 a4 A( t
  261. / K% G$ G; N$ J
  262.   /*Endpoint OUT Descriptor*/0 p! y" g( A( o  j
  263.   0x07,   /* bLength: Endpoint Descriptor size */* h( r4 k0 d. O5 i5 y- E. i" W
  264.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    7 v2 {/ n1 R% H7 X
  265.   CDC_OUT_EP2,                        /* bEndpointAddress */3 b! B0 m  a1 R" ~* \5 m* \7 s
  266.   0x02,                              /* bmAttributes: Bulk */
    + o( R) P8 u7 i& g) A: @
  267.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */! I: i$ l# m% y9 B) f4 F
  268.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  U6 \" h, R; k+ b8 a
  269.   0x00,                              /* bInterval: ignore for Bulk transfer */) x9 e5 s! X; h1 |/ c' ?* S; ]

  270. ; Z8 d3 D0 @; T) y% w4 \
  271.   /*Endpoint IN Descriptor*/
    7 ~) ?3 b: a6 H8 d) J
  272.   0x07,   /* bLength: Endpoint Descriptor size */
    : O5 p% M# w  g& Y
  273.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    / K! Y+ d+ z% m8 ]
  274.   CDC_IN_EP2,                         /* bEndpointAddress */3 p8 b, k$ z. P( O  {( A0 }% k
  275.   0x02,                              /* bmAttributes: Bulk */
    % `% {1 `8 s7 d$ \5 U
  276.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */) S( l* p' X) _, S" q+ |% l
  277.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0 `& z* f7 V7 m$ p
  278.   0x00,                               /* bInterval: ignore for Bulk transfer */
    5 u4 r& e5 K' I- ?+ `; G5 o- ~

  279. 4 {: r: S# ?) K2 E# b
  280.   /*---------------------------------------------------------------------------*/
    $ m# x  N9 \8 t! w
  281.   // IAD  Interface Association Descriptor
    ' I4 [: q, Z. f9 ~. G7 Y2 e
  282.   // 0x08,  // bLength: Interface Descriptor size1 }! {$ G3 e6 J. \( O$ Y( q' U- t
  283.   // 0x0B,      // bDescriptorType: IAD8 g' |7 E& J. ^
  284.   // 0x06,  // bFirstInterface/ D! q' v$ _. C7 ?3 Y
  285.   // 0x02,  // bInterfaceCount
    ! ^/ z$ Q" S$ t$ S$ ~( _. K: H
  286.   // 0x02,  // bFunctionClass: CDC7 U9 l6 J1 [9 }- M- E2 t+ U& E
  287.   // 0x02,  // bFunctionSubClass
    5 c! r: p$ t  Y' z% q
  288.   // 0x01,  // bFunctionProtocol ( U) g% v2 A# l: }* l1 M4 \9 d. f
  289.   // 0x02,  // iFunction# Y& c) }& W" S& e" `: g" }
  290. $ }/ K7 L( a9 t' d9 ^! w8 \' @
  291. /*Interface Descriptor */
    3 L8 A9 r, U& b
  292.   0x09,   /* bLength: Interface Descriptor size */4 F8 {: v. r3 r7 G$ }7 ]3 d
  293.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */% U: |' `; [" E# [  N) G
  294.   /* Interface descriptor type */
    " I/ _. t# }/ ^( I; w2 }' ^
  295.   0x06,   /* bInterfaceNumber: Number of Interface */# O# R  `7 V+ q; f
  296.   0x00,   /* bAlternateSetting: Alternate setting */
    ) [6 U- z9 K2 C6 o6 d  ~6 @
  297.   0x01,   /* bNumEndpoints: One endpoints used */
    7 i! r; ?/ \/ v4 S- L
  298.   0x02,   /* bInterfaceClass: Communication Interface Class */  H6 H0 U  R# i8 B
  299.   0x02,   /* bInterfaceSubClass: Abstract Control Model */
    # m0 A% @5 j' S
  300.   0x01,   /* bInterfaceProtocol: Common AT commands */6 B7 K$ [' D, A; U- W
  301.   0x00,   /* iInterface: */% O( f) n+ j5 L4 m2 \. [
  302. ; v( `2 U  V) R3 D
  303.   // /*Header Functional Descriptor*/) [5 |; R! I& l/ X, ~
  304.   // 0x05,   /* bLength: Endpoint Descriptor size */  E( w( w/ |6 w& T# P7 f( K
  305.   // 0x24,   /* bDescriptorType: CS_INTERFACE */* _' e% p5 z* o. C0 f" u
  306.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */8 n8 L& ?9 j- O' |7 B/ t& V5 W. N
  307.   // 0x10,   /* bcdCDC: spec release number */# F8 j9 K+ }6 @, L7 H
  308.   // 0x01,7 ?  e6 S' E) n& |

  309. + p. V6 N% h0 D2 K) o
  310.   // /*Call Management Functional Descriptor*/
    ( h! A' G* z9 R$ O1 }! w
  311.   // 0x05,   /* bFunctionLength */: [9 n* J% F) ~* X
  312.   // 0x24,   /* bDescriptorType: CS_INTERFACE */; V6 q$ h$ P' O; B& T
  313.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */7 ?7 O0 M! i' Y  t/ V) d
  314.   // 0x00,   /* bmCapabilities: D0+D1 */
    4 U( y* @4 x  D) }0 j) J  u* F
  315.   // 0x01,   /* bDataInterface: 1 */8 K3 ?  P; g# r* E
  316. ; C/ c. ]( Y* l- }  m( M% X; S
  317.   /*ACM Functional Descriptor*/% i+ }3 P( K0 S+ ~! z
  318.   0x04,   /* bFunctionLength */8 D2 e* F+ O5 Q. Y' T. m  @
  319.   0x24,   /* bDescriptorType: CS_INTERFACE */( q# O8 \9 v# V& v8 e7 L, L
  320.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */
    * e% }( X: a' b/ z8 F; S4 ~) K
  321.   0x0F,   /* bmCapabilities */
    * o9 Y9 L& @( C* ]

  322. ' {+ p1 o) s4 |" m1 l
  323.   /*Union Functional Descriptor*/
    " a$ H5 \* k5 o" F0 ?$ R
  324.   0x05,   /* bFunctionLength */  ^4 d- @+ W& u8 J" {( Y+ M2 d0 J( D3 G
  325.   0x24,   /* bDescriptorType: CS_INTERFACE */
    8 j! T. u6 J! S4 B3 j. ?
  326.   0x06,   /* bDescriptorSubtype: Union func desc */
    # g( a* F2 C; E  J& V7 i* D  ?
  327.   0x06,   /* bMasterInterface: Communication class interface */7 g, ^9 i% i" _% q
  328.   0x07,   /* bSlaveInterface0: Data Class Interface */0 c5 z" ]. ?6 ^1 u) Q. f7 e
  329. ; G7 u, L. I* x( Z1 s* `
  330.   /*Endpoint 2 Descriptor*/# v& I2 Q+ g0 }. \8 o
  331.   0x07,                           /* bLength: Endpoint Descriptor size */8 ^* c* i( O+ \8 Q
  332.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */& r- ]) w( v% e2 Y( P2 ]0 d
  333.   CDC_CMD_EP3,                     /* bEndpointAddress */
    ( @  e: h- e9 [5 h
  334.   0x03,                           /* bmAttributes: Interrupt */. Y! \2 J* ^1 S( e" p
  335.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */, D+ H# V/ A8 P* y. T
  336.   HIBYTE(CDC_CMD_PACKET_SIZE),: C, W# ]! W& H+ c% w! S8 V
  337.   0x10,                           /* bInterval: */
    4 a$ @: {  v& V2 b0 @3 r
  338.   /*---------------------------------------------------------------------------*/2 d, `9 _* Q% R- O' `, D
  339.   t$ Y7 q( s) E, P) ^5 {
  340.   /*Data class interface descriptor*/
    - [, ]. N; ^% j3 @& i. q
  341.   0x09,   /* bLength: Endpoint Descriptor size */( }6 N2 D% g- J4 g$ w  R; r% E9 M
  342.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    & d+ x4 ~1 U0 w4 R6 Y5 ~% {) t
  343.   0x07,   /* bInterfaceNumber: Number of Interface */" f( [0 O! [$ a0 Q
  344.   0x00,   /* bAlternateSetting: Alternate setting */
    2 B7 K, F( r! v% I
  345.   0x02,   /* bNumEndpoints: Two endpoints used */; }, s0 Y" y9 }* @6 `7 T
  346.   0x0A,   /* bInterfaceClass: CDC */7 a, V9 n# W/ e' K
  347.   0x00,   /* bInterfaceSubClass: */
    : q8 ?& l6 n+ _) Z
  348.   0x00,   /* bInterfaceProtocol: */" @" m! o! }  V  l5 d
  349.   0x00,   /* iInterface: */
    $ ]) i# W- Q( U1 }" @* W. }) w
  350. 8 T4 `  I8 L" i! \% z3 ]' m
  351.   /*Endpoint OUT Descriptor*/: o: d1 ?! i# z  ~. d5 m
  352.   0x07,   /* bLength: Endpoint Descriptor size */0 ?6 \2 H" s- j, \$ h2 J3 B
  353.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    & O4 `/ s3 y& v1 A$ _
  354.   CDC_OUT_EP3,                        /* bEndpointAddress */
    - z2 M9 r# [7 F# r7 G& \- b# n
  355.   0x02,                              /* bmAttributes: Bulk */
    9 b2 X8 p- X1 Y" k
  356.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */& K% a: j  V' @$ R
  357.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),+ a, ^; T' N4 J/ G
  358.   0x00,                              /* bInterval: ignore for Bulk transfer *// P" e% `: d: m7 w. z
  359. ; k/ M, I. {* l& E5 _  S
  360.   /*Endpoint IN Descriptor*/
    : Y5 U2 m5 Z' l- n  v
  361.   0x07,   /* bLength: Endpoint Descriptor size */8 n0 Z6 i9 N4 ?. V$ j; _4 f
  362.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    - k+ O# U1 P! x% }, J
  363.   CDC_IN_EP3,                         /* bEndpointAddress */
    9 d$ M- H! N  @
  364.   0x02,                              /* bmAttributes: Bulk */
    3 Q; H3 a, G: j4 D  U3 o0 a; M4 ~& M
  365.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    ! p0 \& B& H0 C: ^& R% X9 q' Q2 t
  366.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    * W- v5 G& S( b. o! @0 e
  367.   0x00,                               /* bInterval: ignore for Bulk transfer */9 f4 x$ P3 K2 L) b4 [; p

  368. 6 ^+ V8 N1 ^+ g% b7 w) ^
  369. //   /*---------------------------------------------------------------------------*/8 D6 d; G' C: u
  370. //   // IAD  Interface Association Descriptor
    $ @8 H. X/ K+ T
  371. //   // 0x08,   // bLength: Interface Descriptor size
    ' [2 W+ x% u4 g
  372. //   // 0x0B,       // bDescriptorType: IAD# v# M; j4 e$ O, C( f
  373. //   // 0x08,   // bFirstInterface& P1 }' C' T6 p
  374. //   // 0x02,   // bInterfaceCount
    ( U+ W! l; e* `- I* \
  375. //   // 0x02,   // bFunctionClass: CDC* L; s+ D; y+ Y
  376. //   // 0x02,   // bFunctionSubClass
    ; l* _2 K' {3 _+ v: b$ Q' Q& L; J3 U
  377. //   // 0x01,   // bFunctionProtocol
    3 s# u8 @- A5 t0 x
  378. //   // 0x02,   // iFunction
      d) ?  w( \. w( ]
  379. 3 O7 C/ q& u+ Y: R: j
  380. /*Interface Descriptor */  ~) n& ]" p. r, T: Z- m! p0 }
  381.   0x09,   /* bLength: Interface Descriptor size */
    6 J2 o8 P/ B. ~  G
  382.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: Interface */
    0 ?$ o( n) T) ^! r; ~
  383.   /* Interface descriptor type */1 E5 w6 g/ r; \* U( Y
  384.   0x08,   /* bInterfaceNumber: Number of Interface */
    0 B( g* d+ _3 {4 C* L. p
  385.   0x00,   /* bAlternateSetting: Alternate setting */
    # z7 }. _* A1 S0 y6 K% D+ ^* C
  386.   0x01,   /* bNumEndpoints: One endpoints used */
    2 S- F+ J% M% F5 e& A
  387.   0x02,   /* bInterfaceClass: Communication Interface Class */
    2 n9 C* l4 ~+ y& V& M
  388.   0x02,   /* bInterfaceSubClass: Abstract Control Model *// P* C' V/ N6 m+ O! E
  389.   0x01,   /* bInterfaceProtocol: Common AT commands */
    % W6 N8 s7 r1 d, o; z2 U4 k
  390.   0x00,   /* iInterface: */
    " [4 K" k6 z$ b

  391. 1 c# K! K& P) T7 n; w2 U
  392.   // /*Header Functional Descriptor*/
    * a6 S, r( e) C( X; S( q2 O
  393.   // 0x05,   /* bLength: Endpoint Descriptor size */
    0 F0 N- B7 N, J& b
  394.   // 0x24,   /* bDescriptorType: CS_INTERFACE */
    ( \& d! R1 d: g% M& h, X
  395.   // 0x00,   /* bDescriptorSubtype: Header Func Desc */2 Q, M5 K4 x4 m5 O' s! I, ?! y
  396.   // 0x10,   /* bcdCDC: spec release number */
    " H/ ^# {- j1 g1 {
  397.   // 0x01,
    7 b! [- t/ x9 b% G; A9 }8 Y
  398. 0 Z, b. o& e! w) o# a
  399.   // /*Call Management Functional Descriptor*/4 r- w1 \: g- i9 h
  400.   // 0x05,   /* bFunctionLength */
    6 q% z. ~; e% ~8 @" ~  z
  401.   // 0x24,   /* bDescriptorType: CS_INTERFACE */4 R- o. @6 E6 P8 E# H8 D- u
  402.   // 0x01,   /* bDescriptorSubtype: Call Management Func Desc */3 G/ @. x# S- t0 k" f0 R2 d
  403.   // 0x00,   /* bmCapabilities: D0+D1 */
    - T$ y" s7 N* T; ]
  404.   // 0x01,   /* bDataInterface: 1 */0 N2 a0 L0 }6 A$ x/ S3 F, s* p
  405. 1 d1 Q$ Y/ i6 d$ H! @( K$ i  k7 Q
  406.   /*ACM Functional Descriptor*/
    4 C2 r8 j9 e9 z* K
  407.   0x04,   /* bFunctionLength */
    2 u- C9 ~. e- |+ A* k
  408.   0x24,   /* bDescriptorType: CS_INTERFACE */
    3 g# Y2 K* r3 J2 Z; Z
  409.   0x02,   /* bDescriptorSubtype: Abstract Control Management desc */( F3 Z3 S; z0 l2 N  g; o; j6 i
  410.   0x0F,   /* bmCapabilities */6 F7 Q8 v1 C& v: X
  411. ; [" g- n5 I+ p0 [
  412.   /*Union Functional Descriptor*/, M# i6 \8 Q& j
  413.   0x05,   /* bFunctionLength */
    6 O: c8 F' a  |; }2 Z( l/ Z
  414.   0x24,   /* bDescriptorType: CS_INTERFACE */
    - O. P# [( l8 f
  415.   0x06,   /* bDescriptorSubtype: Union func desc */$ L& G4 f4 v6 J0 @1 p
  416.   0x08,   /* bMasterInterface: Communication class interface */4 |5 `1 P& t  A( j
  417.   0x09,   /* bSlaveInterface0: Data Class Interface */" c7 r! l; ]# ~' w$ v5 {
  418. 7 ]! o5 f0 q8 v4 O0 K( d
  419.   /*Endpoint 2 Descriptor*/0 W+ K9 a6 ?1 \7 o
  420.   0x07,                           /* bLength: Endpoint Descriptor size */
    & J) c! _+ V  x4 a4 ?6 Z* S4 R6 d& b( P
  421.   USB_DESC_TYPE_ENDPOINT,   /* bDescriptorType: Endpoint */
    4 W( G, w' [: m% B8 ]( L
  422.   CDC_CMD_EP4,                     /* bEndpointAddress */
    ) N! t5 i' R: ]% H
  423.   0x03,                           /* bmAttributes: Interrupt */
    " h" u/ F4 F) P, _: a
  424.   LOBYTE(CDC_CMD_PACKET_SIZE),     /* wMaxPacketSize: */
    2 |, c- N, ~1 d1 |- _
  425.   HIBYTE(CDC_CMD_PACKET_SIZE),/ D. S2 ^* O* d6 m' I
  426.   0x10,                           /* bInterval: */
    * B; l) }/ C/ q6 ~4 w: ~  x
  427.   /*---------------------------------------------------------------------------*/
    # j% V# S5 f1 @% i
  428.   /*
    4 C- C* l" Q  q1 r0 V4 n. b8 |
  429.   /*Data class interface descriptor*/
    8 C1 t; A" p! ~1 I
  430.   0x09,   /* bLength: Endpoint Descriptor size */8 G4 e. x4 |( i* R
  431.   USB_DESC_TYPE_INTERFACE,  /* bDescriptorType: */
    ! T  _$ k8 B% a) ]+ e" {
  432.   0x09,   /* bInterfaceNumber: Number of Interface */6 V% o2 n# q( l' N7 c! E
  433.   0x00,   /* bAlternateSetting: Alternate setting */
      j. |9 f. }7 K8 a' P" K
  434.   0x02,   /* bNumEndpoints: Two endpoints used */
    * u0 S$ J+ [/ f1 i
  435.   0x0A,   /* bInterfaceClass: CDC */
    6 Z( N8 A* X7 c: l5 E
  436.   0x00,   /* bInterfaceSubClass: */$ t; y$ ^) v0 U0 y8 |; d
  437.   0x00,   /* bInterfaceProtocol: */" y7 x0 c# s; u* k+ M: G# b) N4 I6 f
  438.   0x00,   /* iInterface: */7 Z+ ], v0 m' n
  439. . x  `& n# Z- B" \
  440.   /*Endpoint OUT Descriptor*/  Q$ u; p0 h+ ~  p3 n
  441.   0x07,   /* bLength: Endpoint Descriptor size */
    1 o7 e- g8 s% Q, F+ D( V
  442.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    . T8 K! {: d9 H. W. S3 n; O- k
  443.   CDC_OUT_EP4,                        /* bEndpointAddress */
    * q- L7 j" E' v' ?
  444.   0x02,                              /* bmAttributes: Bulk */
    $ G" ?' [3 ]/ D- P, d: e3 }! A
  445.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */- b0 }( C0 G0 r1 C( Q: ]
  446.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
    # G: Q6 Q. X- Y
  447.   0x00,                              /* bInterval: ignore for Bulk transfer */  D) t1 I, y3 V

  448. . {: r: z: J, f3 L
  449.   /*Endpoint IN Descriptor*/
    % \. w$ }, e- Z4 f% h
  450.   0x07,   /* bLength: Endpoint Descriptor size */
    8 g/ q- U6 t  B. y( c1 R
  451.   USB_DESC_TYPE_ENDPOINT,      /* bDescriptorType: Endpoint */
    ' Z: r- `2 [0 E
  452.   CDC_IN_EP4,                         /* bEndpointAddress */
    ; [. x0 m3 [0 {0 o
  453.   0x02,                              /* bmAttributes: Bulk */
    . Y, f. o0 w+ l9 d) H- R
  454.   LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),  /* wMaxPacketSize: */
    4 O8 O- ~8 ~( v/ _( g+ O& y
  455.   HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE)," E+ M5 w4 {8 ]' [5 C2 p+ S8 J' I
  456.   0x00                               /* bInterval: ignore for Bulk transfer */
    $ t- A) B9 V6 C3 V0 E
  457. }
复制代码
0 i. H' R& m$ D5 P; a
) c2 h  s+ P+ h: n: |% k/ G
  • 为什么上面有些描述符被注释掉了?
  • 配置5个CDC如果描述符都写上了,这个结构体就超过了255个字节大小,超过了USB2.0最大配置描述符长度
  • 在我的项目中,IAD和联合描述符(/Union Functional Descriptor/)功能一样,我这里注释IAD描述符,不会影响USB,但在windows平台下,它认的是IAD描述符,这个时候就可以注释联合描述符,打开IAD描述符,总之,省略一些非必要描述,减少长度
    2 S. P8 T+ q. a  s: }/ v
  • 这里的坑很多很多,需要很耐心,配错一个字段,千奇百怪的问题就来了
    & N& D: E: A8 L; N) S9 C! Z

    - D+ O! H$ t! g  e& U
3.4 配置PMA---USB硬件缓存
  • 这里又有坑了,我把我知道的都说出
    ( H7 [6 w% v/ b
3.4.1 PMA是啥?
  • 此部分感谢一个大佬的帖子,理解来源与它
  • 这个PMA的作用就是USB设备模块用来实现MCU与主机进行数据通信的一个专门的数据缓冲区,我们称之为USB硬件缓冲区。说得具体点就是USB模块把来自主机的数据接收进来后先放到PMA,然后再被拷贝到用户数据缓存区;或者MCU要发送到主机的数据,先从用户数据缓存区拷贝**MA,再通过USB模块负责发送给主机。
    % y# i! x$ b* k
% n  U! O$ ?6 q: t# N7 K, J

6 p5 p3 P, ^9 f) |3.4.2 5个CDC的PMA怎么配置?
  • 啥也不说,先上代码  i$ k' h% ~1 r3 {  x
# s8 D* e% O: g" s
! C. X) e. k3 U5 ^
  1. u_int16_t ep_addR=0x70; //起始分配地址: 这里是大坑 casojie
    ; }) V4 e- \4 G0 l/ i/ m  P: ~+ F% F
  2. u_int8_t ep_addr_size=64;* R  o0 y: Y3 e% k$ [' B$ e0 g
  3. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;   //此端点是用于USB枚举和基本的通信使用,默认就有,且不可省去# y# X' a4 N5 M  @! E% s; B. I8 A
  4. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
    3 _/ ]# h; e/ z1 s1 J
  5. /* USER CODE END EndPoint_Configuration */2 N' |4 y  y, h* u! U3 `
  6. //CDC0 每个端点都分配了64B% Y. t% x" r% V2 @1 Y, s" i% B
  7. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
    . V8 u/ d* h1 P  p$ Q. _5 f+ U
  8. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
    5 r7 [! }$ f6 P, }/ }

  9. 8 Y* q; E: A4 G
  10. //CDC1                                                                                                //+5
    0 K. }9 X* C; j) \* ^: P7 J1 e
  11. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP1, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  //192 258
    + |) |) ]. H  _2 g7 r8 X
  12. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP1 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;    //272 2A8" X3 ^% J0 m/ L: W( g, P
  13. 9 S; m, W7 u" ]: E& @% t4 x+ @
  14. //CDC2( n+ m7 a5 Y1 R$ O' T: }4 d( F0 l
  15. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP2 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size; //0x270
    0 A/ |1 i4 Q( L  c& v3 |  l
  16. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP2 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;//0x2C0
    4 t3 O1 R7 }' `, O# B' b
  17. " [5 ]9 Y. M; V! Q; ~
  18. //CDC31 _, r. P3 T4 U! v# S( g' z; J- U3 v
  19. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP3, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  //192 258 0x1E0
    ( i0 s3 z3 U8 ]
  20. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP3 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;6 X2 f: s  j) B6 r) N8 `9 I; i
  21. / L: Q& G* }; m/ H/ u
  22. //CDC4  I. B; }: \4 A+ X2 c7 L
  23. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP4, PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;  3 a. t/ ~* N) M
  24. HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP4 , PCD_SNG_BUF, ep_addR);ep_addR+=ep_addr_size;
复制代码

& D3 T) m: }; i5 D" D# C0 E0 e% J# j4 d, I
  • PMA图(我理解的)
    1 x# r8 R2 h" n
* |+ j4 [" B. e; V. N
  • 在PMA的开头部分,是用于记录信息的,这些信息就是:端点缓存区的起始地址:说这简单点,里面写了端点0的缓存区的起始地址是X,端点1的缓冲区起始地址是Y等等
  • 由此可见,当使用的端点数量比较多时,信息记录区索要的空间就比较大,反之,就小,需要动态调整
  • 由大佬的帖子可知,记录一个端点的起始地址信息需要8字节,那么我们五个CDC,则5x2(IN,OUT)=10,再加上0x80 ,0x00端点,一共12个.则12*8=76字节
  • 因此,端点(0x00)分配的地址需要往后偏移,默认的不行,如这次需要76字节的大小,换成16进制,0x4C,我设置了0x70>0x4C,默认的太小了,会导致部分信息记录区被端点0的数据覆盖,而导致部分端点无法使用.! E2 h% Z* W& B9 s; d

5 z. r1 F- q6 F& q3 c
! v8 i0 o; R0 U
4.修改USB初始化代码,新增对新端点的初始化
0 A/ N* X' L$ a5 E" y0 N6 y& P

+ I1 O! c& j5 v4 F, @/ _: m
  1. static uint8_t  USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)# E" N. G, a# n1 {. v. F5 I: ]
  2. {$ M6 x, U) ~% b) F# y1 d* l/ m
  3.   uint8_t ret = 0U;# _0 P3 M& u* C6 w
  4.   USBD_CDC_HandleTypeDef   *hcdc;
    % N$ c( |' z2 f, \+ a

  5. 6 W9 M) B+ a- z9 ~0 \+ m. J" \
  6.   if (pdev->dev_speed == USBD_SPEED_HIGH)
    % ?' {+ @! {9 I: k; T9 U
  7.   {" ~  |; [' m" p1 r/ d
  8.     /* Open EP IN */
    ) l$ [$ l  h- E6 D( _
  9.     USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,4 H' B" E' n8 _
  10.                    CDC_DATA_HS_IN_PACKET_SIZE);
    : M/ r' [& E( E8 N% s
  11.   ^$ s4 l# C0 w. ^8 V
  12.     pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
    + ~( v  }* C* u! B* O3 I, o! d6 V
  13. 0 M! W; p+ ^( f7 R0 D
  14.     /* Open EP OUT */
    : O& N4 _: l6 M+ N, B
  15.     USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,7 j- R4 U% X- b( _* m! H/ ~
  16.                    CDC_DATA_HS_OUT_PACKET_SIZE);
    4 l. z1 K/ y9 U
  17. - K* @, P) b% _
  18.     pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
    - s8 f3 e6 K# `2 f& p( ]6 _
  19. ; ?% Y7 @: O* ^0 [" P! i
  20.   }
    - @. }, T, w0 f& `
  21.   else
    / ?: o& g' y5 o: m( _+ p3 [- `' p1 q' i
  22.   {
    " T5 Y; X: c3 J2 S5 j
  23.     /* Open EP IN */; }$ m9 F  Z; v4 ~
  24.      USBD_LL_OpenEP(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK,
    " C3 a4 @9 Q* }2 I
  25.                    CDC_DATA_FS_IN_PACKET_SIZE);$ c1 P; U5 W. h* U
  26. 7 H1 n! a. w6 I/ @( W/ Z
  27.      pdev->ep_in[CDC_IN_EP & 0xFU].is_used = 1U;
    & z2 @! v* E6 l+ o3 E# Z( t
  28. 8 D# J3 ^) U2 a
  29.     /* Open EP OUT */
    0 b, R( P9 T1 \8 A8 i' z2 a2 M! E6 C
  30.      USBD_LL_OpenEP(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK,
    # y' b4 I( a6 }. ]5 S& l/ D
  31.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    . g( A$ |" e% Z
  32. 0 R" }8 l7 A# g8 q# h. T
  33.      pdev->ep_out[CDC_OUT_EP & 0xFU].is_used = 1U;
    2 _" x2 H; n" j& [
  34. ) l' Z* J$ i, E0 k! J8 h1 A
  35. ) n$ B: {: V8 ?7 q5 e
  36.         /* Open EP IN */
    3 ~  w+ w6 y. R. s- A* t8 V0 r- z
  37.      USBD_LL_OpenEP(pdev, CDC_IN_EP1, USBD_EP_TYPE_BULK,4 j) n" o0 m5 q1 Y: t
  38.                    CDC_DATA_FS_IN_PACKET_SIZE);
    1 {8 K5 ]; r" F5 A: S1 W" d

  39. " |- [4 T: X" T4 A' ?. C
  40.      pdev->ep_in[CDC_IN_EP1 & 0xFU].is_used = 1U;
    3 x, v3 S7 P; s) V

  41. ' D1 T& A5 r+ f
  42.     /* Open EP OUT */
    $ X5 j. {& i, u4 j$ y
  43.      USBD_LL_OpenEP(pdev, CDC_OUT_EP1, USBD_EP_TYPE_BULK,/ z& \8 V# F8 M6 b/ o6 b. O. i
  44.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    : ]7 O- K1 H$ ~2 L' X7 X! H

  45. 3 R3 ~9 I5 t4 R% l7 [
  46.      pdev->ep_out[CDC_OUT_EP1 & 0xFU].is_used = 1U;
    9 i: b0 f/ I- x8 l; K+ Q. A7 h! |
  47. , z/ `& i: t2 w
  48. ' ]4 d+ d6 S0 w

  49. & m# d9 y4 t( G5 V
  50. //--------------------------------------------------------------------
    * Z" I& E1 R! m, N$ P  l
  51.        /* Open EP IN */
    : w$ G* K! m* l& ^
  52.      USBD_LL_OpenEP(pdev, CDC_IN_EP2, USBD_EP_TYPE_BULK,2 Z% R5 `" c/ d( p
  53.                    CDC_DATA_FS_IN_PACKET_SIZE);1 O7 z, Q& A: {& N, o* k! i
  54. 8 a* j# t: z$ `$ v( p! r. N* s
  55.     pdev->ep_in[CDC_IN_EP2 & 0xFU].is_used = 1U;
    ! z  j- `* m! N
  56. , r$ h5 p% \# z* S, F& U2 l: K6 c
  57.     /* Open EP OUT */2 g8 M/ F8 S4 V& x# U" n% {
  58.     USBD_LL_OpenEP(pdev, CDC_OUT_EP2, USBD_EP_TYPE_BULK,
    " A  H; s5 e9 |# r+ r3 h) m$ [
  59.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    + Q  N3 ?$ B, ~, i9 n, j1 c/ V  q
  60. 2 N2 z4 B6 ~' z0 f6 m% {
  61.     pdev->ep_out[CDC_OUT_EP2 & 0xFU].is_used = 1U;
    0 C5 o# d8 j! x( N7 |. c
  62. , P! ^8 R- P1 r& f; T+ ^3 y

  63. - n& P( M. w( G2 o
  64.    //-------------------------5---------------------# ?  b1 C# G# ~2 H2 p1 n* I
  65.            /* Open EP IN */, b1 M1 w9 ]+ M, _- F
  66.     USBD_LL_OpenEP(pdev, CDC_IN_EP3, USBD_EP_TYPE_BULK,, b) h( v. z& R# P
  67.                    CDC_DATA_FS_IN_PACKET_SIZE);! W$ E' t( H# n

  68. 8 {2 o& i# m1 T
  69.     pdev->ep_in[CDC_IN_EP3 & 0xFU].is_used = 1U;! d) b) `8 [4 e  {$ z( J7 ]
  70. 5 U/ E6 ~3 `0 Z& E; y
  71.     /* Open EP OUT */) L9 Y/ X  j& P/ L* K) \- h, S
  72.     USBD_LL_OpenEP(pdev, CDC_OUT_EP3, USBD_EP_TYPE_BULK,1 m& j1 C; q4 v! v$ |
  73.                    CDC_DATA_FS_OUT_PACKET_SIZE);
    ' O2 `) y" Y' P3 t9 N9 g
  74. 6 A3 T% U$ c/ _6 c
  75.     pdev->ep_out[CDC_OUT_EP3 & 0xFU].is_used = 1U;0 o$ W. q+ S$ k7 d0 ?" C" t
  76. ! D  N# F/ m& ?4 s- \' p! Y, ]
  77.     //-------------------------5---------------------
    ; ~6 u& H: Q- C7 H. I+ N' l1 Q6 E( [
  78. ( S, A& P0 y$ w$ B3 a
  79.            /* Open EP IN */
    7 p0 [3 U/ H  a8 {& g
  80.     USBD_LL_OpenEP(pdev, CDC_IN_EP4, USBD_EP_TYPE_BULK,
    5 b) \3 D" s* `* i7 I  L
  81.                    CDC_DATA_FS_IN_PACKET_SIZE);
    # q8 _  w, P6 ^9 b
  82. 9 B+ d% E. o+ |0 l( Z# V! ?  }6 e& e3 ]
  83.     pdev->ep_in[CDC_IN_EP4 & 0xFU].is_used = 1U;
    6 W3 L' K# P! w

  84. . B1 C2 C5 ~2 Z, {6 X; {
  85.     /* Open EP OUT */" G5 r$ h2 n$ ?. G: U/ [7 x, U$ E
  86.     USBD_LL_OpenEP(pdev, CDC_OUT_EP4, USBD_EP_TYPE_BULK,# e/ _! _4 N7 D6 }
  87.                    CDC_DATA_FS_OUT_PACKET_SIZE);/ R- B* A2 H0 f8 s3 m% F
  88. * N/ y% |" v" A
  89.     pdev->ep_out[CDC_OUT_EP4 & 0xFU].is_used = 1U;
    $ [! r! G# L$ d6 A  R6 d) {

  90. : P, v8 L* G8 d- `& w5 I5 [: B, v
  91.   }+ X" y" C2 S" {7 K5 q' w6 j, ^5 S$ q
  92.   /* Open Command IN EP *///控制端口无效,不要取消注释
    4 R" N+ m. q( h; ?; S
  93. //  USBD_LL_OpenEP(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);; X: y8 f- R) i% E
  94. //  pdev->ep_in[CDC_CMD_EP & 0xFU].is_used = 1U;  d4 ~! M& l2 `4 M3 U
  95. # X( E$ p, X% s3 {

  96. ) h" E2 u+ g/ h
  97. //   USBD_LL_OpenEP(pdev, CDC_CMD_EP1, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
    9 Z* k3 h! ~! N1 E. q6 q3 r; S: H
  98. //   pdev->ep_in[CDC_CMD_EP1 & 0xFU].is_used = 1U;# @: r. e6 R8 H5 X) {/ u

  99. ; t1 Z% T+ l  _+ K

  100. 0 x# }9 z2 c4 K1 }9 x' N& L) Y
  101. //     USBD_LL_OpenEP(pdev, CDC_CMD_EP2, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);
    , d9 H. W2 u6 H8 G) Z/ |
  102. //   pdev->ep_in[CDC_CMD_EP2 & 0xFU].is_used = 1U;
    ! L& L6 p5 M) E
  103. # I. V# o( W. [# y5 Y
  104. % _" K& ]; E( b8 p
  105.   //   USBD_LL_OpenEP(pdev, CDC_CMD_EP3, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);8 C" {3 ^" E! M( p  e1 z
  106.   // pdev->ep_in[CDC_CMD_EP3 & 0xFU].is_used = 1U;
    . L3 T9 l) X4 H
  107. 8 _: \; h" G( A" t: S: f, d) T
  108.   pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
    + s% R: r8 l* I; [8 C; E$ C: t' ~
  109. , D* l7 D6 J' C) r8 q3 H' Z" e
  110.   if (pdev->pClassData == NULL)  q. u, R3 X( Z% B) X( N- P+ S
  111.   {
    : l+ Z( H3 i5 F/ l$ p( \' Z' f
  112.     ret = 1U;5 B2 B# V# _0 v
  113.   }$ u2 \0 X$ {5 J0 m) m4 s
  114.   else* H3 D% ]; t; Z  O7 x
  115.   {
    4 ~: l0 q% P" g' V( ]
  116.     hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;0 k9 d' r0 U" p

  117. 5 }9 l% u, [, v/ p& I
  118.     /* Init  physical Interface components */
    - P$ Z0 _- \- C4 S$ Y' m+ U
  119.     ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();% X+ F/ v7 P$ F4 Z- `1 U, _& C- M; c
  120. 3 u5 N& q! n5 ~
  121.     /* Init Xfer states */
    * \( Q. A3 i. e8 L/ H
  122.     hcdc->TxState = 0U;
    / D* ~% g& O! c' p* u; g
  123.     hcdc->RxState = 0U;: p# m6 n  d3 J9 s& @0 f  ^

  124. , c& w/ c, ]5 E( d2 r3 Z/ ?
  125.     if (pdev->dev_speed == USBD_SPEED_HIGH)
    7 U* W. P$ _3 o9 T
  126.     {/ k) o& ?( N" R/ y$ R1 r  _2 v
  127.       /* Prepare Out endpoint to receive next packet */
    4 @* Q' ^! i* `9 G! k$ i, [1 j8 S
  128.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,
    # u" I6 [# z/ Z8 Q( }7 l. Z
  129.                              CDC_DATA_HS_OUT_PACKET_SIZE);
    2 X9 D" @& N0 B0 @
  130.     }
    ! l3 z; C% n0 p% q5 J$ u5 u' J
  131.     else1 @& m) I8 J3 K3 }2 K- B5 Y
  132.     {' r( F( i. B6 w1 s
  133.       /* Prepare Out endpoint to receive next packet */
    ( m, L; a0 k( H" i7 S
  134.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer,) k( J! ^, d' V* _3 v+ [# Y2 w
  135.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    6 H0 W! H3 E. i
  136. / ^) y$ T2 z. j) G: S
  137.                                    /* Prepare Out endpoint to receive next packet */' v0 O1 p* K$ n$ e% M* A
  138.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP1, hcdc->RxBuffer,
    ; W4 y! [5 A7 T' b8 b
  139.                              CDC_DATA_FS_OUT_PACKET_SIZE);: N2 V( m+ `' w& r6 r% A

  140. . d0 q: x# g9 k% j1 ^
  141.                                    /* Prepare Out endpoint to receive next packet */( o. J1 {5 `; G* s4 C$ o
  142.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP2, hcdc->RxBuffer," s% n* U  C# }3 A+ S, {
  143.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    + d/ T( G' ~3 l/ L8 z. P& a9 J

  144. 0 I% S6 v9 s5 Z# C, j8 c
  145.                                    /* Prepare Out endpoint to receive next packet */, T2 {# i" t- x: j! V
  146.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP3, hcdc->RxBuffer,) ~0 g5 G5 |' l* x6 z
  147.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    % J9 n1 L1 S8 v  V

  148. ) l4 C9 n* |& Y. ^6 q! \! r
  149.                                                              /* Prepare Out endpoint to receive next packet */
    ; D6 g: w  h; X; X5 Q+ M
  150.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP4, hcdc->RxBuffer,
    ! u( `0 B0 a' j! q/ R# c# y, R
  151.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    ' _  W! V4 E6 C7 }) ~' }" q! Z5 r
  152. & U* b$ g& x+ s  t
  153.       USBD_LL_PrepareReceive(pdev, CDC_OUT_EP5, hcdc->RxBuffer,
    + V: k8 E8 ~4 q. p/ f5 ^9 h
  154.                             CDC_DATA_FS_OUT_PACKET_SIZE);- m8 ]* c4 J' D0 I; N1 d. U4 M' r
  155.     }+ c* m' V. ?8 a
  156.   }
    ' K) K* G3 Z0 v' Z1 f# G
  157.   return ret;
    - X( \: y8 m! q9 x) m( s% P
  158. }
复制代码

$ d5 W5 c2 s( p2 `; {6 y3 f. B& c( I: g) S. ^0 C* I
5.修改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)
    + X9 w. @1 O/ }* I+ N- M: g  f

  • 先说说这几个函数的关系:CDC_Transmit_FS---调用--->USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev)
  • USBD_CDC_DataOut(数据接收回调)---调用--->CDC_Receive_FS
    6 f: h3 D) u  _& V. f! X( ?

CDC_Receive_FS(uint8_t *Buf, uint32_t *Len)修改为CDC_Receive_FS(uint8_t* Buf, uint32_t *Len,uint8_t epnum): 此后所有OUT端点来的数据都将进入此函数,可通过参数epnum区分
% [- K' H; i) [* E
  1. static uint8_t  USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)9 B* J5 ^: h5 K" z. u7 N8 M5 N
  2. {
    4 z7 i$ \5 h/ \- Q& V% j+ I# _4 d
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;
    $ W! Z2 _4 j' f7 f3 c; U

  4. ; X9 a/ V: @9 R
  5.   /* Get the received data length */
    6 q9 t' P8 ]$ V: l9 d9 j4 @
  6.   hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);
    7 \# Y4 _/ g3 N: o
  7.   /* USB data will be immediately processed, this allow next USB traffic being% U: ]  o# J, `5 k# z8 d" X
  8.   NAKed till the end of the application Xfer *// `% h8 [* |- Q: N
  9.   // printf("USBD_CDC_DataOut.1294:Len:%d :EP:%02X\n",hcdc->RxLength,epnum);
    2 k( ?  j2 a1 ?4 @! C, g/ }& L5 s
  10.   if (pdev->pClassData != NULL)! g1 H" x7 c. ?
  11.   {' ^" I1 e) z3 o
  12.     ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength,epnum);//此处修改,加入端点,相关的函数声明也跟这这样改' `& N5 L. [7 V5 B! H0 Q# N
  13.     return USBD_OK;
    ( w& P9 z$ p) I6 c( Z
  14.   }
    & P  H# S3 s3 D; N' N: M
  15. ) S7 f3 \- p2 z0 f: O# ?( f
  16.   else
    " P& h- z" u0 p
  17.   {
    2 v7 |5 E3 ^% p/ A1 S' h" T
  18.     return USBD_FAIL;# w# M& |. M/ G# B! }
  19.   }# x  E. p8 @) l, _3 o# H
  20. }
复制代码

& l9 y4 i2 ^( {7 q
  • CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)该为CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum):只是增加一个参数,函数体不用动9 c& F! r- ~1 w4 C) y

( A! f, |4 [+ d- E3 v$ s
& `8 m  J' ]/ U& O" L( C9 }' Q
  1. uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len,uint8_t epnum)
    / {/ J& o- |$ i  n; X- ^( \. S
  2. {& D1 p% V  v3 k. B
  3.   uint8_t result = USBD_OK;
    " ]5 Q$ k1 l6 w9 I+ ~) Q
  4.   /* USER CODE BEGIN 7 */- a  V) r$ U' x6 ~  b0 E( U
  5.   USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS_CDC.pClassData;
    0 A6 C1 @7 v* P8 m
  6.   if (hcdc->TxState != 0){5 R% }9 t" y: m
  7.     return USBD_BUSY;
    % n+ t2 v9 r" D8 `8 j4 E
  8.   }" {+ L# I8 V# o( x. Z
  9.   USBD_CDC_SetTxBuffer(&hUsbDeviceFS_CDC, Buf, Len);6 [! k/ |/ E6 k# i% {/ b' j. D% X7 V
  10.   result = USBD_CDC_TransmitPacket(&hUsbDeviceFS_CDC,epnum);    //将epnum的端点传到这个函数,这个函数也需要改
    9 B" A- Y9 Q' W# P6 n- w+ ]% S
  11.   /* USER CODE END 7 */
    ! [- ?" W* V- ]; d: n# T2 x
  12.   return result;
    8 G8 f" J2 T; _" A' _
  13. }
复制代码
7 F; t' v3 Z5 {% z$ L5 n
! I! c  \6 s; x3 u
  • USBD_CDC_TransmitPacket的修改* E: [# c- p* Z, e  e
  1. uint8_t  USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev,uint8_t epnum)
    . {5 U+ e7 I' v2 H3 k9 e
  2. {4 h. B, d( _. C
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;% f+ q6 G- N  q7 U3 q. ?3 G" _" z

  4. ' n. P' Y1 T0 _
  5.   if (pdev->pClassData != NULL)5 |( @  x! V5 t
  6.   {
    ) `8 U, d* N& D& s5 P& w$ K
  7.     if (hcdc->TxState == 0U)' l" \8 k# G' u' M  S+ v
  8.     {
    1 D- ~- C: x& U
  9.       /* Tx Transfer in progress */" y8 d6 `# L  _' E& _2 {
  10.       hcdc->TxState = 1U;+ [$ E/ S7 p4 P+ ^; ]
  11. " A( A' {/ ~3 L1 ]9 e5 t, c
  12.       /* Update the packet total length */
    / P4 c5 y& Q" j
  13.       pdev->ep_in[epnum & 0xFU].total_length = hcdc->TxLength;//将原本的CDC_IN_EP更改为我们传入的端点
    0 d% c$ N0 J: p$ ^: T+ |) Z, Y$ a
  14.       /* Transmit next packet */
    / ~( F3 j5 h, l5 `9 i
  15.       USBD_LL_Transmit(pdev, epnum, hcdc->TxBuffer,1 E* [8 B  B/ _8 e0 ^
  16.                        (uint16_t)hcdc->TxLength);//此处也是' L3 Y& d+ P5 X4 O7 n0 o$ Z5 ^0 m, Q8 i
  17. + f" y% p' o- c' `
  18.       return USBD_OK;( O2 p2 w2 \# a# w( a' R. y
  19.     }
    9 c9 T6 ?0 \9 X. L/ \6 {
  20.     else
    $ z9 y5 V) ~# _& W( ^
  21.     {* J! q6 }3 T( W4 \- L8 {
  22.       return USBD_BUSY;
    7 w( p+ v! b: o" M4 C
  23.     }. d% R8 m" {" r
  24.   }7 S! l# L* @, i" @4 ^: ~$ _- S2 m5 |
  25.   else
    5 C# l0 R+ ?1 s5 v
  26.   {: H6 q9 i# R/ q9 U  l1 P  }3 O" Z
  27.     return USBD_FAIL;% Q# s6 P- b" Q$ ~) {: m
  28.   }
    ! Y8 a( W3 A0 A" h5 \9 c
  29. }
复制代码

, I* m1 Y8 Z) k" J; j: i$ |6 L6 x5 J  D4 r: \( V3 x7 t

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

% N- f8 G3 ]. a$ {1 @' U
  1. uint8_t  USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev,uint8_t epnum)
    : N' F; L3 n. j5 |. h1 L( r; o
  2. {$ V6 `/ T3 ^: ^' P0 X
  3.   USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef *) pdev->pClassData;- u2 f3 S+ s* T% f8 q9 i# Y- i

  4. 1 f; n- l+ y1 E- P1 i9 `- @- X
  5.   /* Suspend or Resume USB Out process */
    ' t! m' y  d( {" `" ~& Y# e, y6 O0 O2 @
  6.   if (pdev->pClassData != NULL)+ Z! f- ]6 h# I% R  h, g! m3 Y
  7.   {6 ]" X+ E: U& y1 W( Y1 d
  8.     if (pdev->dev_speed == USBD_SPEED_HIGH)# O' Z$ E" Y' O& V0 k' Y, j
  9.     {
    ! ^) W7 j+ t+ b* P5 y) m2 E
  10.       /* Prepare Out endpoint to receive next packet */
    % G  U7 K2 i) D+ Q) f8 X$ l$ ]
  11.       USBD_LL_PrepareReceive(pdev,4 V$ A8 A* l: z  h
  12.                              CDC_OUT_EP,. H+ q/ O- {, O2 _6 f
  13.                              hcdc->RxBuffer,& j4 E# K; r) Z0 h- I* M
  14.                              CDC_DATA_HS_OUT_PACKET_SIZE);! Z7 O, G# Y4 x  G9 p6 Y
  15.     }
    6 b$ e9 A: N0 p# A( N* c2 v; F6 p' {
  16.     else' J) j- R5 r. P  z& `% p! c2 T& L& F
  17.     {
    4 ~4 N5 ]# E6 F4 G" ~0 J+ @
  18.       /* Prepare Out endpoint to receive next packet */
    + w) C+ J6 H. |1 v- _; z* o% _
  19.       USBD_LL_PrepareReceive(pdev,
    ) }& s+ t0 X; Z+ u5 f
  20.                              epnum,
    / q( L% a$ [: x: c( \4 O
  21.                              hcdc->RxBuffer," D! D) S7 m0 T% V! Q, O9 [2 X* f& a. z
  22.                              CDC_DATA_FS_OUT_PACKET_SIZE);
    3 b; @$ D6 K5 o' c: v3 n: ^
  23.     }
    0 m+ C8 q9 y8 d% {. S7 J" c
  24.     return USBD_OK;9 k2 z4 C* H& R1 k
  25.   }, n- v* o: \2 k- R! D
  26.   else& J' O( |+ h, c4 m) c7 t' w
  27.   {
    & S1 }0 l# T5 ~1 v: a, D
  28.     return USBD_FAIL;' k! T* ^( m* B5 ~
  29.   }
    . @9 J' _7 ~+ L6 S6 w+ d+ C
  30. }
复制代码

: y' H+ d9 O( O
对以后而言,我们就使用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了
! f& V4 f. ]% a5 p# W. g, a* F
6.后续
  • 此时就完成了,不过不排除有些深层的问题。
  • 如:当五个CDC同时在Read时,其中一个close,有可能会导致其他四个都无法再Read出数据,需要重新Open,但在电脑的深度depin系统上并没有这个问题,在项目中的板子上就有,希望大佬们提供下线索。感激不尽  e5 J5 j0 `* u  ^0 h. @* x1 ]

+ x# X6 t' U* x8 x3 Z( n. w/ W
+ y; K2 }3 C9 W* m' T/ R" h+ @) A转载自:casojie
! Z$ v! F  y  P4 }. P
赞 收藏 评论0 发布时间:2023-1-3 19:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

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