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

【经验分享】STM32 USB虚拟串口

[复制链接]
STMCU小助手 发布时间:2022-1-13 21:00
串口调试在项目中被使用越来越多,串口资源的紧缺也变的尤为突出。很多本本人群,更是深有体会,不准备一个USB转串口工具就没办法进行开发。本章节来简单概述STM32低端芯片上的USB虚拟串口的移植。在官方DEMO中已经提供了现成的程序,这里对修改方法做简单说明。
2 q# K5 f* v& _2 E4 t: u2 n
$ E9 }3 `# M9 V7 h( D; a, m  f
首先打开官方demo我们开始进行移植,第一步复制我们可用的文件,操作如下:
Projects\Virtual_COM_Port文件夹下,复制红线部分
图1
2 H& D' `! e) W; k0 \
300035032772082.jpg

$ p6 c2 P& I5 b
图2
" A4 K, C4 R7 d* J/ e
300035202932682.jpg

  n/ A/ K* c' U9 h/ P# j, F
我为了方便演示统放在usb/src文件夹下:
图3
1 d+ f! C- }. A9 b. V; r5 ^
300035313246246.jpg

0 R% |1 D, m% n; d; ?
现在复制USB的库文件,这些文件不需要我们修改:
图4

# W1 |' ?1 s; H, |/ I9 `
300035404189967.jpg

2 M5 }+ v. o9 L7 G) \3 ~+ `
上图中的文件统一放在usb/lib文件夹下:
图5

% u0 ]/ H  A3 p# g- G/ G
300036032935279.jpg

* ]! _  p7 p; _5 M3 E' _% L2 o! m* B, o- k, j. G
         好了现在所需要的文件我们以复制完了。这里先讲一下DEMO程序的主要工作流程:

  y1 B4 z( l0 d0 a( Z4 ~" I
300036178402768.png

2 K. r" G" o* R$ B- I. f' @; `
图6
         由上图可知,PC通过虚拟串口发送数据到STM32 usb口,STM32再通过usart1发送数据到PC串口。我们做项目时,只用USB虚拟串口即可。所以我们现在需要把串口发送部分删除。把USB做为一个COM口来使用。我们要如何使用这个USB口呢?demo中是把USB发送数据做了一个缓存,先把要发送的数据存入缓存中,然后由USB自动发送出去。而接收部分是直接通过串口透传。我们在应用时就需要用到两个FIFO,1是发送,这个和demo方式是样;2是接收,接收也做一个缓存,我们通过查询来判断是否收到新数据。这下大家应该明白为什么使用两个FIFO了。 我这里有写好的FIFO库函数可直接使用Queue.c文件。
         现在开始修改:
1,stm32_it.c 更名为usb_it.c删除无用代码,只保留usb中断函数,和唤醒函数。代码如下:
代码1
  1. 1 /* Includes ------------------------------------------------------------------*/
    + ]$ m2 g3 Y! \( h, g. w2 ~
  2. 2 #include "hw_config.h"+ _3 V/ l( Q# M4 g9 ~9 \' m' j% ]
  3. 3 #include "usb_lib.h"
    8 {/ M1 }: g% X
  4. 4 #include "usb_istr.h"! j7 \( i- w+ W# ?
  5. 5
    ) D- I' h" @9 R! v6 |, }" v
  6. 6 * _: o* }1 J% b! M' s5 w$ D
  7. 7 /*******************************************************************************
    8 a7 Z# i' h, `2 H& M/ n" D
  8. 8 * Function Name  : USB_IRQHandler8 v1 Z( L) l" o- M: B3 a+ r
  9. 9 * Description    : This function handles USB Low Priority interrupts
    ' p0 G- g5 L* y4 N
  10. 10 *                  requests.
    ' v! k2 u0 N4 F! j& a
  11. 11 * Input          : None1 q$ v# F* N4 R1 s- u" [5 l
  12. 12 * Output         : None
    1 w. i4 Z/ f! e
  13. 13 * Return         : None* W. X9 z- a+ g9 q& G3 |' N' y
  14. 14 *******************************************************************************/
    6 O+ J: s, ^! ~6 f, b7 l
  15. 15 #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)|| defined (STM32F37X)& u% f" o4 v) f1 G( N/ _
  16. 16 void USB_LP_IRQHandler(void)* L6 J4 d% M! N0 v8 t" y
  17. 17 #else
    5 R0 R% R: @' S1 ?4 D
  18. 18 void USB_LP_CAN1_RX0_IRQHandler(void)6 x- }6 H4 Q. ^! y' X- y
  19. 19 #endif
    ) g2 {. `( S3 ?6 s) S' n* c
  20. 20 {
    % l7 Q+ v# Y, j* N9 j" Q' V8 z
  21. 21   USB_Istr();
    3 R* s( s5 n' w+ K& A. H
  22. 22 }
    . e9 `) O0 t1 ~. r" g" K
  23. 23
    " S3 |7 M" H( n+ r! l2 N
  24. 24 /*******************************************************************************3 g* D. N+ |  C( d
  25. 25 * Function Name  : USB_FS_WKUP_IRQHandler, l3 M* p- M) }- w4 e
  26. 26 * Description    : This function handles USB WakeUp interrupt request.* s+ R% B$ e( K  i# e  ^
  27. 27 * Input          : None
    6 [3 J. H4 ?7 t* i" B( p
  28. 28 * Output         : None
    8 Q: ^+ m. Z& X' `9 Q% _$ [( Y
  29. 29 * Return         : None
    : }( C3 ?/ j" a
  30. 30 *******************************************************************************// Z5 H$ ^: ]+ A/ T4 V4 i* L
  31. 31 - Z) x7 b$ |1 ~% y& Q7 @0 u% c7 K
  32. 32 #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)' Y" z0 b3 {0 N0 L$ U4 O
  33. 33 void USB_FS_WKUP_IRQHandler(void)+ O8 l" B. Q) v% @9 Z
  34. 34 #else7 r  B7 a# K8 ?; O& I) W. v
  35. 35 void USBWakeUp_IRQHandler(void)
    9 S, \$ x& f7 j1 Q
  36. 36 #endif2 P" B  x; I; I$ v. L/ q6 t
  37. 37 {. N  a: C2 y$ ?4 Y7 a+ ?4 G' B' x/ O
  38. 38   EXTI_ClearITPendingBit(EXTI_Line18);. C6 Y9 h  S; ?+ [- q( _2 U5 r& r
  39. 39 }
复制代码

- O+ H" L4 P8 S/ P4 x, O( {+ t
2,修改代码hw_config.c删除无用代码,新建立2组,读FIFO和写FIFO的函数。后面会用到。
代码如下:
代码2
  1.   1 /* Includes ------------------------------------------------------------------*/& Z! d6 P, s/ p1 ~4 a
  2.   2
    + `% a6 b4 Y( d* p: S+ Z& f
  3.   3 #include "usb_lib.h"
    5 N  p6 T; Z/ f. A3 Y2 x7 d" L3 \: M& ?
  4.   4 #include "usb_prop.h"' t, T; A1 {" f  ~% C) q$ x) q
  5.   5 #include "usb_desc.h"
    0 m8 Z6 U" q. x
  6.   6 #include "hw_config.h"
    - U( x! n! g6 P
  7.   7 #include "usb_pwr.h"
    7 x. Q0 ~9 D! n& r& A- j
  8.   8 #include "Queue.h"$ W, n0 z  c5 O; H; q4 U& D0 P2 q, n. m+ a
  9.   9 $ S, N9 p/ {8 O( G1 q3 R8 Q
  10. 10
    8 ^  r; x1 P. S
  11. 11 /* Private typedef -----------------------------------------------------------*/
    , B+ A- E- I& ?$ I# o  x& \
  12. 12 /* Private define ------------------------------------------------------------*/- X' J% a- p3 x6 q, P
  13. 13 /* Private macro -------------------------------------------------------------*/# @  [: R5 G( z9 j- T+ Q& z% P
  14. 14 /* Private variables ---------------------------------------------------------*/
    # m8 L5 O  `+ T; o; o
  15. 15 ErrorStatus HSEStartUpStatus;
    9 n0 Y( Y' _% V" H/ x/ ~
  16. 16 USART_InitTypeDef USART_InitStructure;- T6 E6 `0 h) H5 W0 `7 h
  17. 17 EXTI_InitTypeDef EXTI_InitStructure;  U3 Y9 }7 N  V, L
  18. 18
    3 Z4 m6 n1 w& Z8 w8 h1 Q7 m
  19. 19 ; a1 x1 w2 Q2 }& |/ n; N6 k
  20. 20 #define USB_COM_RX_BUF_SIZE         (1024 + 256)
    . L: m; z' A5 L3 p- J4 F
  21. 21 #define USB_COM_TX_BUF_SIZE         (1024 + 256)
    " f& \6 I$ [; ^3 ?/ `
  22. 22 . s6 M& d3 `, ]+ i6 r9 k
  23. 23 static QUEUE8_t m_QueueUsbComRx         = {0};
    9 f( n7 ~9 J# c1 o; b
  24. 24 static QUEUE8_t m_QueueUsbComTx         = {0};( T; }8 a& R. t" r# x' T# u
  25. 25 static uint8_t  m_UsbComRxBuf[USB_COM_RX_BUF_SIZE]      = {0};     0 o7 b9 h+ m* H1 i0 k9 Z" H
  26. 26 static uint8_t  m_UsbComTxBuf[USB_COM_TX_BUF_SIZE]      = {0};   9 ~3 v% |+ l/ f0 `- T* I
  27. 27 . T4 E9 l/ l. e4 h& H
  28. 28 static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);  V2 H  k: n: f
  29. 29 /* Extern variables ----------------------------------------------------------*/
    + h, G! E" ~1 d& |8 t6 Z( E9 C
  30. 30 ' g3 X0 ^" W  L
  31. 31 extern LINE_CODING linecoding;
    , }  r7 v6 ^) l( Q& [, |
  32. 32 # p. c+ D* n. V
  33. 33 /* Private function prototypes -----------------------------------------------*/5 T5 m: I1 P3 W" Y
  34. 34 /* Private functions ---------------------------------------------------------*/# A1 W/ g4 d; @
  35. 35 /*******************************************************************************
    1 U) o9 D+ M+ B* j" N6 Q4 t& x
  36. 36 * Function Name  : Set_System
    1 F$ C$ X0 i6 }" ~, V% D  C
  37. 37 * Description    : Configures Main system clocks & power# J) x; n8 v  y$ r/ D
  38. 38 * Input          : None.
    $ W1 m. X1 j0 D; B2 U
  39. 39 * Return         : None.  T# f! I' j& G0 f
  40. 40 *******************************************************************************/( x+ p1 ?( T* L7 s) p$ u$ D
  41. 41 void Set_System(void)1 H) e+ b# }# x: H
  42. 42 {1 j0 [3 r* J/ O& h
  43. 43   GPIO_InitTypeDef GPIO_InitStructure;! q2 n, |. R3 `& O, ~4 j
  44. 44
    + b$ P3 Y; N+ w" G$ m
  45. 45   QUEUE_PacketCreate(&m_QueueUsbComRx, m_UsbComRxBuf, sizeof(m_UsbComRxBuf));
    5 Y* D/ ^7 J& F0 x3 [5 Q5 M
  46. 46   QUEUE_PacketCreate(&m_QueueUsbComTx, m_UsbComTxBuf, sizeof(m_UsbComTxBuf));0 P" ~5 A% l6 k; Q& n+ t; ~
  47. 47   6 L9 f; P& N0 T! A" k
  48. 48   /* Enable USB_DISCONNECT GPIO clock */
    4 f9 I( R! l4 H; q
  49. 49   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);! J9 B1 X7 O: z9 |
  50. 50 ) H5 t5 L/ @  `6 f& o& M
  51. 51   /* Configure USB pull-up pin */
    - n2 J! l! [. t( L. s: W- q" |+ x
  52. 52   GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN;
    * r9 d) z/ |  ^& `3 ]# i% O9 Z5 O
  53. 53   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    ; s( v% Q2 z( x( Y; v4 ~
  54. 54   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    3 x2 e& j1 V# @9 v
  55. 55   GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);- ]" A$ M+ R0 F& X, G7 s
  56. 56   ; _* T( Q! P. y
  57. 57   /* Configure the EXTI line 18 connected internally to the USB IP */! L, M, b: \* L% D
  58. 58   EXTI_ClearITPendingBit(EXTI_Line18);
    5 ?& D6 d0 H& f- W% S( e: O
  59. 59   EXTI_InitStructure.EXTI_Line = EXTI_Line18; * {/ d+ ^' @! c/ g+ H
  60. 60   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;- F8 q) X+ w4 @4 u" N
  61. 61   EXTI_InitStructure.EXTI_LineCmd = ENABLE;. l5 E% X- r, F$ U2 s% R
  62. 62   EXTI_Init(&EXTI_InitStructure);
    * y3 V4 I( v6 {5 s, T
  63. 63 9 B% Y: V+ ~5 T" `9 S
  64. 64   ! k* g0 n- ^9 {- a" A
  65. 65 }
    ! V6 m% M& N2 N% }- H
  66. 66
    ; c5 M; ^  Q( K$ m  n6 F4 h
  67. 67 /*******************************************************************************$ N/ `7 J4 G3 ~! m% v
  68. 68 * Function Name  : Set_USBClock9 j+ @3 ]: N9 ~+ i9 x
  69. 69 * Description    : Configures USB Clock input (48MHz)* J* D, Y1 g2 o) A" m. J
  70. 70 * Input          : None.! p$ V. S* \/ [0 \3 N# }
  71. 71 * Return         : None.
    2 t! ]2 @* g3 y) v- V5 m
  72. 72 *******************************************************************************/. H0 F4 u7 k/ O( b9 O
  73. 73 void Set_USBClock(void)# l% A- B9 J7 \& l/ i
  74. 74 {1 X) v* \* @4 n) [
  75. 75   /* Select USBCLK source */
    . T, B" P- r; }2 n# [/ G
  76. 76   RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);" ]6 S: e( k  {& @0 }
  77. 77   ! \& P; B" J, e  h" o: X' Y: j
  78. 78   /* Enable the USB clock */( q8 t6 \) c; Y) o
  79. 79   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);2 E& ~3 x; x/ X
  80. 80 }
    ; o7 U4 l# d) ^9 b5 I; U
  81. 81
    7 \4 Q4 J/ j' e
  82. 82 /*******************************************************************************
    ( E/ W' ?$ S7 T* |8 ]
  83. 83 * Function Name  : Enter_LowPowerMode
    9 X% V& c* `! q5 C0 O0 m2 S
  84. 84 * Description    : Power-off system clocks and power while entering suspend mode
    4 R2 e0 J( _; B6 s' z5 i" O
  85. 85 * Input          : None.: v7 a0 @9 f- s8 }6 b" j5 l
  86. 86 * Return         : None.7 o& U/ L8 _+ ]0 T) _* l7 d
  87. 87 *******************************************************************************/3 ~: ]; Y3 {) j
  88. 88 void Enter_LowPowerMode(void)
      _# G& H7 q" v0 M
  89. 89 {: F* I# s( }# S6 e$ n" `
  90. 90   /* Set the device state to suspend */
    : K: z0 l/ H6 n5 \, v# k2 }
  91. 91   bDeviceState = SUSPENDED;- c/ i2 u( j8 f0 W! v6 `: ^
  92. 92 }
    3 u2 H% l7 B1 R* h
  93. 93 * t& H0 r$ z( U
  94. 94 /*******************************************************************************) T* Z  x* B3 N0 k/ k; U
  95. 95 * Function Name  : Leave_LowPowerMode
    ( ~& x9 p1 h5 L1 d7 ?# P
  96. 96 * Description    : Restores system clocks and power while exiting suspend mode
    + ^. J+ a+ X% I' s/ N% J/ p" R
  97. 97 * Input          : None.3 X: \9 c, {! V7 o
  98. 98 * Return         : None.
    ( |+ W6 X0 b! {5 i+ `' v% S) H
  99. 99 *******************************************************************************/$ ?6 j* c0 S4 J) z* S) c: K. Q
  100. 100 void Leave_LowPowerMode(void)
    1 C; G# N- z( t4 z5 \3 U( Y
  101. 101 {. K# C5 _% G% V8 J
  102. 102   DEVICE_INFO *pInfo = &Device_Info;; C8 g. G( G( \) g
  103. 103
    ) {' ^: B6 J8 A0 @
  104. 104   /* Set the device state to the correct state */8 O- ]$ A4 k9 f
  105. 105   if (pInfo->Current_Configuration != 0)# ^, t5 W$ W7 A+ Q% U
  106. 106   {
    ! b6 c+ v& s) H* R3 G
  107. 107     /* Device configured */
    0 H( e1 O3 l/ {" |6 i! g& J
  108. 108     bDeviceState = CONFIGURED;! K" b. o. N9 \$ c0 x
  109. 109   }
    % V9 n$ l3 K- g2 i5 F7 Y3 O* C- m
  110. 110   else: a5 Y" T8 G% k. l$ G, @4 `
  111. 111   {# B4 R# R2 D% j- b
  112. 112     bDeviceState = ATTACHED;
    2 r' Z1 b% R6 N8 e/ ~
  113. 113   }
    / B1 p" L# S5 X" s- b/ |9 Z
  114. 114   /*Enable SystemCoreClock*/
    # z# y; j, p  z7 w: G$ l# I8 y
  115. 115 //  SystemInit();
    / C- }; u; S* P& V. i. C
  116. 116 }5 s) q9 T2 Q. }; k
  117. 117   `' V+ e+ D1 D) i( v; m* \
  118. 118 /*******************************************************************************
    9 G6 I' t5 B4 @; R+ {
  119. 119 * Function Name  : USB_Interrupts_Config1 \) N1 |3 _/ I5 ~7 i
  120. 120 * Description    : Configures the USB interrupts
    ) b- |# O( r* w7 }; O: r
  121. 121 * Input          : None.: K6 ~" b8 D  P. ^3 g+ U! @
  122. 122 * Return         : None.
    3 l' X4 o( e  g: m5 j. P1 e# Y
  123. 123 *******************************************************************************/
    ! c5 q+ D# {' i/ H. \
  124. 124 void USB_Interrupts_Config(void)
    & s1 W: I4 y# X6 t! z3 I
  125. 125 {! ?4 U4 z. S, E; ]  \: v/ _
  126. 126   NVIC_InitTypeDef NVIC_InitStructure; 7 R( n, J1 T+ v) ^
  127. 127
      y" ]; z' p3 ^2 A7 c
  128. 128   NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;, ^+ F. M% q! u7 \9 q$ u* @
  129. 129   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    6 T  C5 M* d* g8 Z8 x6 {2 U
  130. 130   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    $ l, a( F% m- |
  131. 131   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    # A$ `, L( D5 I2 `  g* R% S
  132. 132   NVIC_Init(&NVIC_InitStructure);: U5 F2 c0 W0 r
  133. 133   $ h6 P5 h9 l4 g0 n8 r6 z+ X
  134. 134     /* Enable the USB Wake-up interrupt */1 x" U" M" Q$ X* C& i6 p
  135. 135   NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
    " D  Y) C" R* z: J
  136. 136   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    ' `  E8 t5 W0 m$ n
  137. 137   NVIC_Init(&NVIC_InitStructure);; @# N' ]1 ?: N. m
  138. 138 }
    # [% i9 i; D8 c  v8 V
  139. 139
    : I+ y6 J: J" y' T; E* g& A
  140. 140 /*******************************************************************************  T* J5 j) ]; X$ j9 p. C, x
  141. 141 * Function Name  : USB_Cable_Config
      \) m' D5 ]+ \3 F$ k) L
  142. 142 * Description    : Software Connection/Disconnection of USB Cable9 \1 c1 }  m* m8 Y. T6 n
  143. 143 * Input          : None.9 n/ U0 e1 z& J0 s- I7 J
  144. 144 * Return         : Status+ ?. F2 r3 ?: p" m0 p
  145. 145 *******************************************************************************/
    3 d3 W) |& {8 P3 c  l1 s
  146. 146 void USB_Cable_Config (FunctionalState NewState)
    ' \/ T5 a0 f* Q
  147. 147 {
    9 ^+ C/ g9 z* g  q: f/ u
  148. 148   if (NewState == DISABLE)
    $ A. v5 L" m5 P
  149. 149   {0 s% Z7 M" `$ v% d
  150. 150     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    5 w3 ?6 D6 R* `
  151. 151   }5 e$ w' X5 m$ a( O5 d
  152. 152   else; X; u0 Y5 S( h7 O& H
  153. 153   {8 [7 R9 c! F, i
  154. 154     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    , r8 m& R) ~' r( Z+ ^
  155. 155   }2 P3 u) \0 C( _* V7 c
  156. 156 }" n* ~8 i. X' i5 ]- l+ i
  157. 157 : I+ ]8 m! C8 g7 Z1 Z
  158. 158 /*******************************************************************************
    5 G+ |5 d) V9 r  K4 w- x2 a
  159. 159 * Function Name : void USB_Config(void)/ p6 L* }, e- X* C
  160. 160 * Description   : USB系统初始化
    4 d1 }% I1 K: ]3 B
  161. 161 * Input         : * i8 R  X2 A: E; L4 H" [. Y4 k
  162. 162 * Output        :
      K* r, U1 F4 t# c9 f; }
  163. 163 * Other         :
    ; I* e0 @" L) D" R+ p' M
  164. 164 * Date          : 2014.11.285 O# e' v* V2 {& A
  165. 165 *******************************************************************************/
    / k1 E- i+ X, ?
  166. 166 void USB_Config(void)
    0 z& U; ?, I3 K" ?' c0 k+ `
  167. 167 {
    4 z3 i5 [/ g, Q
  168. 168     Set_System();3 q/ @! `  M4 W5 n
  169. 169 " U! x% o( \! V$ ~4 ~
  170. 170     Set_USBClock();
    4 |: q# R/ q9 }4 ~
  171. 171
    ; V6 E8 V" g) B+ S
  172. 172     USB_Interrupts_Config();% M1 j$ \& Z; t6 y/ e! T5 x# v: \
  173. 173
    3 m3 v% \) E2 W0 r- U
  174. 174     USB_Init();3 `5 O0 x( C4 C) f$ v
  175. 175 }
    ( S: ]5 G( @. x' \. l6 K0 w; X
  176. 176 ' a1 n' x4 s3 w8 A8 w2 @
  177. 177 /*******************************************************************************- V$ [: j. ^3 j, x, h
  178. 178 * Function Name : uint32_t USB_RxRead(uint8_t *buffter, uint32_t buffterSize)% I; T) l, C1 A( i  H( d7 m: ~2 x
  179. 179 * Description   : 从USB接收缓存中读数据, W; W+ i3 U* u1 L3 A9 D
  180. 180 * Input         : & S! A1 {% }+ l5 J
  181. 181 * Output        : : o; L8 ?& @( I! f
  182. 182 * Other         : : V* k5 I$ T& F7 ^3 C4 ]5 k
  183. 183 * Date          : 2014.11.28
    ( I' a2 c- M- m2 \4 l' `3 r
  184. 184 *******************************************************************************/* c$ q! l0 Q* t$ |0 i- a  C6 p
  185. 185 uint32_t USB_RxRead(uint8_t *buffter, uint32_t buffterSize)
    ) k) w" j' y: X8 o
  186. 186 {* P: r+ Z/ g2 P" x5 {$ q- J
  187. 187     return QUEUE_PacketOut(&m_QueueUsbComRx, buffter, buffterSize);
      I( O* U  C2 @" j/ G
  188. 188 }
    ' U0 {9 [! m0 F
  189. 189 /*******************************************************************************. v6 n# e" h( a& K: K! W
  190. 190 * Function Name : uint32_t USB_RxWrite(uint8_t *buffter, uint32_t writeLen)
    - ^, c. |2 k7 g
  191. 191 * Description   : 写数据到USB接收缓存中
    , U$ W* a% ?5 ]' Y& Q; N+ Q7 k
  192. 192 * Input         : ( r& n% j- ]+ N. H( J
  193. 193 * Output        : $ F, O1 `8 v9 b3 ?2 `4 u6 e
  194. 194 * Other         : % W9 U5 q0 Z  \. |1 L5 U2 K9 K9 A5 H
  195. 195 * Date          : 2014.11.28
    ' D0 G0 c; S+ r5 g" B
  196. 196 *******************************************************************************/
    " b2 U. {9 |0 N) l
  197. 197 uint32_t USB_RxWrite(uint8_t *buffter, uint32_t writeLen)
    4 ?% [% @$ E) t. x+ E! U8 s5 g) s
  198. 198 {* a4 {% o5 M+ z5 ~6 y+ L5 E' p/ e
  199. 199     return QUEUE_PacketIn(&m_QueueUsbComRx, buffter, writeLen);
    8 V: `- E2 o  ~2 a( @! S5 P5 {4 Q
  200. 200 }
    + W4 Y) [% H4 a  V) V! K: ~: \3 }$ F
  201. 201 /*******************************************************************************1 T! e: N% }" d) a
  202. 202 * Function Name : uint32_t USB_TxRead(uint8_t *buffter, uint32_t buffterSize)% Q: ?# M! u2 l/ N1 J# `$ j* B
  203. 203 * Description   : 从USB发送缓存中读数据
    1 W: A9 Y( _$ S6 ~% R2 |) D
  204. 204 * Input         :
    ) K" _7 a+ c% ^9 G( s
  205. 205 * Output        :
    8 ]! p* Y: N' H4 E: w
  206. 206 * Other         :
    / d' q! Y& N& ^2 h1 T
  207. 207 * Date          : 2014.11.28
    ( i0 S8 f" c7 z' f+ H+ h
  208. 208 *******************************************************************************/
    6 A, X% i0 T2 j3 j
  209. 209 uint32_t USB_TxRead(uint8_t *buffter, uint32_t buffterSize)7 X! d, v, z" m( }9 g6 ~
  210. 210 {* u/ a% i9 r  u1 j/ i: ]+ S
  211. 211     return QUEUE_PacketOut(&m_QueueUsbComTx, buffter, buffterSize);;
    & L- J2 x3 u9 E! ]: f
  212. 212 }# Y" O+ E9 S5 H2 {
  213. 213 /*******************************************************************************
    + k4 r) w6 D* l) c2 S# t/ z
  214. 214 * Function Name : uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)2 @: h9 f( y+ U  [* i( Z# u- R
  215. 215 * Description   : 写数据到USB发送缓存中
    ' Y+ j- p) L/ z' e' i# t. j
  216. 216 * Input         :
      J+ h% \" O1 c, a% n8 R0 r! K
  217. 217 * Output        : 2 ?+ B) n/ R) V$ ^2 p3 `
  218. 218 * Other         : - w4 V! r3 b' l  S4 O6 J
  219. 219 * Date          : 2014.11.28
    ; l4 X6 e! |0 C# v, [& o; L
  220. 220 *******************************************************************************/. H9 B  i6 ^- K) a. u
  221. 221 uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)  U4 o% ], m/ ^% O9 J" [
  222. 222 {3 w% j8 ^# C" M  ^
  223. 223     return QUEUE_PacketIn(&m_QueueUsbComTx, buffter, writeLen);' t& P: k  u$ R: N
  224. 224 }- X: I5 ^+ M) d, Q
  225. 225 1 l0 x" e' e$ `, \9 z* f
  226. 226 ( c) y( ?( Q: {" j% a1 n4 @7 D. a
  227. 227 " u& r+ {, p" J! y; P3 Y- n% e0 |
  228. 228 /*******************************************************************************; H$ A+ V1 X8 K* R6 A6 j
  229. 229 * Function Name  : Get_SerialNum.
    6 ]- X0 l! z- d* A  V# O
  230. 230 * Description    : Create the serial number string descriptor.
    1 h9 r9 M/ p5 u. z" f+ Y
  231. 231 * Input          : None.
    3 y- h6 J4 L" I* f6 K8 I
  232. 232 * Output         : None.9 S8 K% k7 M# [. n: A# M
  233. 233 * Return         : None.% n! E: _- \) j6 ^7 n
  234. 234 *******************************************************************************/
    ! b* ^; b8 S+ f2 U: J0 C& r" X7 U
  235. 235 void Get_SerialNum(void)* R: G- U9 \4 d2 t  v* g* Z/ s7 h2 x
  236. 236 {
    9 k/ Z3 h! w( d4 a
  237. 237   uint32_t Device_Serial0, Device_Serial1, Device_Serial2;) H0 P3 z  g. z4 c4 x7 b8 i
  238. 238 ' @7 M" W& k. u0 ?6 @
  239. 239   Device_Serial0 = *(uint32_t*)ID1;
    ' j# m3 f& y  A* p- y
  240. 240   Device_Serial1 = *(uint32_t*)ID2;) @) P) o& x9 O! o1 a/ ?
  241. 241   Device_Serial2 = *(uint32_t*)ID3;  
    ! q, V5 d; Z0 ]4 C
  242. 242 7 L% }% o' I2 @- T5 V
  243. 243   Device_Serial0 += Device_Serial2;
    & @3 F# V. F: ^; ?$ p6 b& x
  244. 244 ( t" j2 Y" h6 v# ?3 F
  245. 245   if (Device_Serial0 != 0)3 z' f1 T' m2 k+ S* {$ _! y( c8 h
  246. 246   {& @+ |4 J: O4 M4 S8 m8 Z2 z  s
  247. 247     IntToUnicode (Device_Serial0, &Virtual_Com_Port_StringSerial[2] , 8);
    " D  r* _8 A/ O9 c0 `5 {+ W) i
  248. 248     IntToUnicode (Device_Serial1, &Virtual_Com_Port_StringSerial[18], 4);% P" _$ k$ p/ \3 y9 t( K
  249. 249   }: R( D  [. V, {. b% a2 t+ R7 i& w2 d
  250. 250 }
    # [. b; I* C9 `: X: m6 K! q
  251. 251
    4 U6 a/ Y, _* L/ i) a( p/ i7 I
  252. 252 /*******************************************************************************1 H  T2 S2 e( F+ l* C; K
  253. 253 * Function Name  : HexToChar.) C/ \2 T! i9 w  ?& l$ \( v
  254. 254 * Description    : Convert Hex 32Bits value into char." g& b' k) [! ^
  255. 255 * Input          : None.9 ]  [* }" z+ m
  256. 256 * Output         : None.$ w: I" u& N  c$ ]; x* A/ J
  257. 257 * Return         : None.* ?4 P! V9 `/ z" z5 D, H
  258. 258 *******************************************************************************/# {0 R; H; i' N8 j% E: |6 g6 s# D
  259. 259 static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)! S' g9 K; S- \. h! c8 f
  260. 260 {
    # z% }1 B+ u1 W4 y' E( L$ ]
  261. 261   uint8_t idx = 0;! x- S6 N8 o% {5 Z9 _
  262. 262   
    * y. L+ ?$ z  X$ @
  263. 263   for( idx = 0 ; idx < len ; idx ++)
    ! y% T$ Z% C- s% B; a
  264. 264   {; c$ H% ?' Q2 d+ u
  265. 265     if( ((value >> 28)) < 0xA )
    + P4 _1 x* i+ S+ G/ J; M) D2 h% b
  266. 266     {" ?9 |$ [: Q6 X) `5 C5 G
  267. 267       pbuf[ 2* idx] = (value >> 28) + '0';4 K" @" f- R, ]0 [* I& e# p# s3 w5 _
  268. 268     }+ X! e5 d8 h( s% s9 r% E7 R
  269. 269     else% o- q5 R' w. ?$ n% n
  270. 270     {
    7 c! f6 w6 O3 c; J
  271. 271       pbuf[2* idx] = (value >> 28) + 'A' - 10; ! y% j2 J7 l: y8 R, e! W
  272. 272     }
    % H2 m. d. i& z+ C
  273. 273     0 ?4 r2 E% t1 R  H
  274. 274     value = value << 4;
    2 ~# [' q9 w; {1 U: A% t/ p$ V* e
  275. 275     
    ! Q9 h, {% N3 P, j3 ^
  276. 276     pbuf[ 2* idx + 1] = 0;
    * G7 q$ O9 X! C3 X
  277. 277   }
    2 p' _$ ]0 B! D: ]) G) C
  278. 278 }) l; |% S# I5 q: n- M0 I6 p& {
  279. 279
    3 D4 r+ F' E) p+ j3 K
  280. 280 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码
# F- c) ?* k, l/ X' P6 p% U

% X; b. I$ p8 w
这里要讲一下为什么要屏蔽SystemInit(),因为demo只运行虚拟串口功能,在USB未插入的情况下,是进入低功耗状态,插入时从低功耗状态退出后会调用此函数。当然我们在项目中一般不会这样,系统是否运行和插USB接口没有联系。所以我在下文中把进入低功耗代码屏蔽了,自然也就不用唤醒代码了。
图7

. A. M0 h+ ^% s; P* D3 r; W
300038465597900.jpg
1 z7 }9 P% Q& f7 G
关于USB口使能控制引脚,需要根据开发板的引脚定义来修改宏定义platform_config.h文件中,笔者使用的是神舟3号开发板,控制信号刚好和demo相反,所以修改hw_config.c代码如下:
代码3
  1. 1 /*******************************************************************************  I% D; ]! E5 w4 y% B8 y8 w# W" I5 z, [
  2. 2 * Function Name  : USB_Cable_Config1 C/ u- J3 h9 ~
  3. 3 * Description    : Software Connection/Disconnection of USB Cable: n/ q2 z3 t# e1 c- M
  4. 4 * Input          : None.
    3 D) X1 v8 J5 N9 D/ E* Q& E) u; E
  5. 5 * Return         : Status2 @1 \& p$ Z% {+ ]2 V( g
  6. 6 *******************************************************************************/
    1 ^# M0 K5 t/ {! N" J0 g
  7. 7 void USB_Cable_Config (FunctionalState NewState)" @% ]: P- \" x/ [. C4 }
  8. 8 {& [( P( c; ?5 d3 [" _1 [
  9. 9   if (NewState == DISABLE)
    , D9 T  [( h: o$ U
  10. 10   {
    6 H" Z% B1 L8 ?  x/ Y
  11. 11     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);# g6 P: y0 o. D& Z( B5 l0 }
  12. 12   }# H, y' r/ J' [
  13. 13   else& ], W- {) L# S3 S2 |
  14. 14   {
    : V+ B4 ^/ Y' Q9 d' o: V! _0 ?* m
  15. 15     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    3 I% x2 c& H7 S8 p. V& W; U" |
  16. 16   }" g5 R1 Q" L- g  C; p& O
  17. 17 }
复制代码

; s: a  I( M, Z* w
3,现在修改USB 回调函数中的代码usb_endp.c文件。使用下文代码替换:
代码4
  1.   1 /* Includes ------------------------------------------------------------------*/
    , P5 o5 B8 @- e
  2.   2 #include "usb_lib.h"* u$ k, \7 O5 y. n
  3.   3 #include "usb_desc.h": {" r. W9 |, _, K" B1 n( i  K
  4.   4 #include "usb_mem.h"
    ! Q4 v7 r: [0 _$ e  r6 T( `/ E
  5.   5 #include "hw_config.h"
    ) x2 Z* }: h, h7 ^4 p
  6.   6 #include "usb_istr.h"" F# p' G: u( g4 A$ h, d( _" [
  7.   7 #include "usb_pwr.h") x& S7 q% m( [. C0 F3 h$ i
  8.   8 ) F) f' O) Y3 U' a% f" B5 d
  9.   9 /* Private typedef -----------------------------------------------------------*/
    4 ^- Z- ~4 S1 `* H! h# W
  10. 10 /* Private define ------------------------------------------------------------*/
    ' W5 t, K& M' D# C" a7 T, y
  11. 11 ( R% y& M/ I. Y
  12. 12 /* Interval between sending IN packets in frame number (1 frame = 1ms) */
    ; S; f( P- B0 c
  13. 13 #define VCOMPORT_IN_FRAME_INTERVAL             5( o6 n6 V4 ?6 q0 U  w- S
  14. 14
    & F  s( E: \. c$ D' w5 x3 [: r- G
  15. 15 /* Private macro -------------------------------------------------------------*/
    ! b" M8 {8 E, }- R# j
  16. 16 /* Private variables ---------------------------------------------------------*/
    / W3 [" W" ~3 ]% s8 m: E
  17. 17 static uint8_t txBuffter[VIRTUAL_COM_PORT_DATA_SIZE] = {0};
    6 U6 s$ `* ~: K% _
  18. 18 static volatile uint8_t txFlg = 0;) Y" |. Y! `4 ~% B# c  W) T- o
  19. 19 static volatile uint32_t FrameCount = 0;- b, Z2 u4 {6 v6 s9 l3 @$ l7 K
  20. 20
    8 H' R( Z3 `+ \8 ]7 l, c7 H
  21. 21
    ; ?( X7 Y0 k2 A2 U( Q# [
  22. 22 /* Private function prototypes -----------------------------------------------*/
    5 [6 W) j; J' R0 ~
  23. 23 /* Private functions ---------------------------------------------------------*/1 B* A6 \  [. }
  24. 24 * ^* D) f5 u/ H0 M
  25. 25 /*******************************************************************************7 Y* S) k; `" q% n6 n: \  X
  26. 26 * Function Name  : EP1_IN_Callback
    % ?$ L: ?3 x+ F# [* x
  27. 27 * Description    :* h8 }# C: B" i( V
  28. 28 * Input          : None.  ?$ e: a6 l0 b
  29. 29 * Output         : None.
    + `6 n; T% N& l$ M
  30. 30 * Return         : None.
    6 `# ^# F' N, O) ?1 a/ ?
  31. 31 *******************************************************************************/
    0 w3 Z$ T, ]5 \
  32. 32 void EP1_IN_Callback (void)
    5 n" G- N- g3 N2 R
  33. 33 {
    ( T/ d, {& e( b  `- X
  34. 34     uint16_t len = 0;; b) C- g$ F, s  M2 }; `, u
  35. 35     - v" Q4 B) t( [* t; k8 [2 c" Y
  36. 36     if (1 == txFlg)& L8 J& N$ U( @; l% K: R
  37. 37     {4 W6 U* _' m# ^8 V
  38. 38         len = USB_TxRead(txBuffter, sizeof(txBuffter));1 t: E; c1 d. W6 m
  39. 39 ) ]/ n# l) |4 H; \- X4 d  `
  40. 40         if (len > 0)( f( R3 J$ ^* M# N; n5 ^
  41. 41         {& F- s( E8 T- x( W3 [
  42. 42             UserToPMABufferCopy(txBuffter, ENDP1_TXADDR, len);5 L7 Q' `+ u% K' e0 _
  43. 43             SetEPTxCount(ENDP1, len);
    % r  |- E" I% q/ h4 h+ p) s2 h
  44. 44             SetEPTxValid(ENDP1); : U3 X5 p& ~5 c
  45. 45             FrameCount = 0;
    / H, k5 g/ W. }$ |
  46. 46         }0 N% k  y7 B; x$ u9 u, v; D
  47. 47         else* o- q/ M! q  ?5 S  @
  48. 48         {
    ( |: ~1 Z4 x* s+ S* b2 |) ~3 ?
  49. 49             txFlg = 0;
    ! Z6 R0 [' T  ^0 W- A$ k
  50. 50         }
    , o) G% w0 O% Q- Q) H  k, _
  51. 51     }( [; G( c$ L, Z5 N
  52. 52 }
    8 e! e5 _3 ~  J- f0 x
  53. 53
    % ^0 p7 t$ p, q7 o' Q9 o5 U: A
  54. 54 /*******************************************************************************
    . P3 q" [- ^6 p% A) x
  55. 55 * Function Name  : EP3_OUT_Callback: M% J: P2 @' J1 v/ s! B
  56. 56 * Description    :1 Q: B. K' X% X& }: ]# t
  57. 57 * Input          : None.
    4 F( o+ d1 Z! x7 L$ Y* |9 L
  58. 58 * Output         : None.8 ]6 w! k) F8 {2 S* _5 ?
  59. 59 * Return         : None.5 }" B7 U, ^, ~7 D+ H- g1 T
  60. 60 *******************************************************************************/
    3 {4 P+ Y6 k+ o3 p( Q3 o& S
  61. 61 void EP3_OUT_Callback(void)0 U" g3 ^* }7 a1 X" Q% Q6 L$ }# O
  62. 62 {
    * _- I1 t$ X) R& e5 {6 q
  63. 63   static uint8_t buffter[VIRTUAL_COM_PORT_DATA_SIZE] = {0};
      I, ]  I  z7 F% u+ p
  64. 64
    4 I" z- R1 T6 V' R' b" A! z. m
  65. 65   uint16_t USB_Rx_Cnt;7 S; ?2 {/ a! v" {' {% U* U+ g
  66. 66   " p) k  h- c0 ?
  67. 67   /* Get the received data buffer and update the counter */- a$ ?8 j; |" H4 h- ?* v
  68. 68   USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, buffter);9 J& X% t7 c8 o8 j7 Y1 `% y
  69. 69   & Y* Y8 U! X- H: P! H1 n
  70. 70   /* USB data will be immediately processed, this allow next USB traffic being 4 S8 J5 s) u8 L
  71. 71   NAKed till the end of the USART Xfer */
    5 S; ~5 Q% ~9 v% H6 Z( R* M4 _( N
  72. 72   USB_RxWrite(buffter, USB_Rx_Cnt);
    6 Y* D) F9 a: |6 Y
  73. 73
    # T/ ?4 w2 g, Q# P) r
  74. 74   /* Enable the receive of data on EP3 */
    1 k; L) v2 t4 d8 A. d$ b
  75. 75   SetEPRxValid(ENDP3);
    * H! |- C8 M7 ?# b
  76. 76
    5 X, ^1 R& w! ?% H/ o
  77. 77 }3 ]" c; R6 i! B0 g- J7 v" `
  78. 78 5 s" i- I7 |; X# E" d) _4 ~
  79. 79 0 N: v& [6 _- L6 t( @7 {$ X
  80. 80 /*******************************************************************************
    $ n( U: |. z" Q. y+ y: E
  81. 81 * Function Name  : SOF_Callback / INTR_SOFINTR_Callback
    9 v- p( ]( p9 z; I% E2 l% M
  82. 82 * Description    :
    ( R% f6 z+ g8 ^2 E
  83. 83 * Input          : None.
    $ m9 N, J+ E  g+ W; h& ]
  84. 84 * Output         : None.6 ?5 x* I, e% |0 u/ _. I
  85. 85 * Return         : None.2 q* ^& I4 y0 L7 h
  86. 86 *******************************************************************************/9 q' b; a( x% I3 W
  87. 87 void SOF_Callback(void)
    * n3 i) N, [2 Y! t
  88. 88 {) i  A; X' f/ S( Y4 z/ v3 ]' f
  89. 89     uint16_t len = 0;
    / ^9 A* _6 j" I5 J3 T' v- O! o
  90. 90
    0 z' b" `: w5 t" i% d
  91. 91     if(bDeviceState == CONFIGURED)+ s: ^& l. {* F
  92. 92     {
    " o" K. o$ l) f+ F0 l' r9 N
  93. 93         if (0 == txFlg)0 O$ I6 l- C  i6 O8 l
  94. 94         {; n8 b$ o" `" ~0 e3 n8 J' U
  95. 95             if (FrameCount++ == VCOMPORT_IN_FRAME_INTERVAL)
    ! U$ d2 S- G; `0 [
  96. 96             {
    " t" [* }2 \/ A/ H1 ^# w
  97. 97                 /* Reset the frame counter */
    1 i- B0 e1 c1 d. q  i- C
  98. 98                 FrameCount = 0;  y) S* ], D% h. I. [; j
  99. 99 6 d8 C( C  f8 w( u! p; f: `
  100. 100                 /* Check the data to be sent through IN pipe */
    # ~8 M" v. _- s$ Y6 @' R
  101. 101                 len = USB_TxRead(txBuffter, sizeof(txBuffter));
    : Q* f: `  i! b) Y- ~$ ^
  102. 102 ' {( H6 f& M' I: D
  103. 103                 if (len > 0)
    ; K0 ?. E! @( ]1 i
  104. 104                 {
    1 j0 j. U# z2 ^- D. g: e+ O% @
  105. 105                     UserToPMABufferCopy(txBuffter, ENDP1_TXADDR, len);6 A! B( z" w& ]% r. R, I& q
  106. 106                     SetEPTxCount(ENDP1, len);
    . d3 F1 `0 C) {% g+ g8 C
  107. 107                     SetEPTxValid(ENDP1);
    / r  b/ ^' b5 m/ d& a- N
  108. 108
    7 s2 ^3 D: a6 }: V" ^/ g! O" T
  109. 109                     txFlg = 1;+ {/ T4 N) D: `% {$ Q
  110. 110                 }* H0 L$ [. U: q, `
  111. 111             }
    5 P  o3 d5 d+ z. l2 u! I
  112. 112         }# i  y4 N9 u& c5 a
  113. 113     }  
    " |5 \3 j3 J3 N
  114. 114 }% r* u- v, S  j- S" F* r; X
  115. 115 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码

. E7 j1 m- v2 e" l# C/ A$ t  ^* k8 Z" d8 J9 ~
这里讲下大概意思,函数EP3_OUT_Callback是在USB口收到数据后,将数据存入FIFO中。
函数SOF_Callback定时查询用户是否有要发送的数据,如果有则进行发送,在发送完成后会触发发送中断EP1_IN_Callback函数,如果发送完毕就不调用SetEPTxValid(ENDP1)函数,发送完成后就不会再触发EP1_IN_Callback函数。
4,修改usb_pwr.c在前文中说到:不让系统进入休眠状态,这里屏蔽185行 __WFI();
5,修改usb_prop.c屏蔽COM初始化代码。137行USART_Config_Default(); 237行USART_Config();
6,修改usb_desc.c 这里修改需要参考一些USB专业的书籍,推荐全圈圈的书,讲的通俗易懂。关于本程序的驱动,笔者在win7下测试可以自动安装,如果无法自动安装可使用文章开始的链接中的驱动程序。本文件如果修改需谨慎,其中pid,vid是制造商ID和产品编号,如果修改了那驱动也要对应修改,官方驱动就无法自动进行安装了。
到这里移植就差不多完成了,下面进行测试。由于USB虚拟串口不受波特率限制,所以笔者进行过50k/s的压力测试,运行半小时未丢1个字节。
移植好的工程STM32_UsbVirtualCom.rar也一起存放在上文章开始的链接中。

/ K) B2 V5 _  g, n1 L0 d
收藏 评论0 发布时间:2022-1-13 21:00

举报

0个回答

所属标签

相似分享

官网相关资源

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