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

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

[复制链接]
STMCU小助手 发布时间:2022-1-13 21:00
串口调试在项目中被使用越来越多,串口资源的紧缺也变的尤为突出。很多本本人群,更是深有体会,不准备一个USB转串口工具就没办法进行开发。本章节来简单概述STM32低端芯片上的USB虚拟串口的移植。在官方DEMO中已经提供了现成的程序,这里对修改方法做简单说明。
3 P( B$ N' w4 S) f; J

* h' a3 b# y: o8 {
首先打开官方demo我们开始进行移植,第一步复制我们可用的文件,操作如下:
Projects\Virtual_COM_Port文件夹下,复制红线部分
图1

- f* E1 o4 Z, v- v/ @5 R2 l) q9 }
300035032772082.jpg
8 w# J5 j4 \. K% F" K  \
图2
, k, r* d( l  C4 T
300035202932682.jpg
1 x% W: K# e! s! W( d5 u. }
我为了方便演示统放在usb/src文件夹下:
图3
3 @1 t6 ~$ L: L# w
300035313246246.jpg
! l1 k! X9 {/ T, v) ~
现在复制USB的库文件,这些文件不需要我们修改:
图4

2 E) u. }6 M8 ?7 V& b' ]
300035404189967.jpg
6 {, S! o: g, W3 L/ M: M% g
上图中的文件统一放在usb/lib文件夹下:
图5
- G& Y# ^2 [+ K
300036032935279.jpg
+ r; t& n, ^0 a+ E5 a3 d) }) ^) ?
+ C- s2 I$ T5 ^" |* n$ N8 [4 R; t
         好了现在所需要的文件我们以复制完了。这里先讲一下DEMO程序的主要工作流程:

; [* j3 N5 V" V; }
300036178402768.png

5 t7 s7 Q9 J/ Y
图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 ------------------------------------------------------------------*/# e6 `1 Y* l# A5 p% u& n
  2. 2 #include "hw_config.h"3 e6 K8 Q1 C; _0 w* \. ^) }  A2 p
  3. 3 #include "usb_lib.h"; L4 l, _, e+ ?7 D
  4. 4 #include "usb_istr.h"( ^  k$ g! b, n" Q& b) ?% `
  5. 5
    6 g5 w& |7 \  h- N
  6. 6
    . x, P4 ^8 M9 D' r5 O
  7. 7 /******************************************************************************** B4 R7 b% u& N8 ~8 f
  8. 8 * Function Name  : USB_IRQHandler
    3 C& V" Q! F6 s9 @
  9. 9 * Description    : This function handles USB Low Priority interrupts
    8 V5 K; d8 s5 _# b, C/ q
  10. 10 *                  requests.# _6 d- q- Q& m1 L$ ]
  11. 11 * Input          : None
    " j+ h& q- C) ^+ Y
  12. 12 * Output         : None
    4 F" }8 w" Q" Q3 d: m% k6 P. w
  13. 13 * Return         : None
    3 k6 E5 p7 p7 o& q
  14. 14 *******************************************************************************/
    0 @; O% ~8 m4 C7 o. E0 p
  15. 15 #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)|| defined (STM32F37X)
    ; K! A1 t2 c- e# ~: x; W3 m
  16. 16 void USB_LP_IRQHandler(void)( N1 Q. d" P( N' L
  17. 17 #else
    ! y% o3 \7 J( V5 z* G
  18. 18 void USB_LP_CAN1_RX0_IRQHandler(void)
    % j0 t. ?) G7 S" E  P% M9 Q
  19. 19 #endif
    / ~& W$ X; K# \3 N1 v' \3 n
  20. 20 {
    : {# d3 h3 K" Y7 C
  21. 21   USB_Istr();
    % x* B0 X- ^% X4 {' s
  22. 22 }1 F1 b2 U$ ]& a, J+ Y
  23. 23
    ! J, o( R# Z4 T2 C7 D( p$ }
  24. 24 /*******************************************************************************
    3 C2 X, _9 s9 K3 Q( ~( V. G; q4 F' r6 N
  25. 25 * Function Name  : USB_FS_WKUP_IRQHandler( |4 ]% Q. W/ x0 G4 B4 y6 `/ k
  26. 26 * Description    : This function handles USB WakeUp interrupt request.! y# Y2 Z5 s7 X+ b+ v+ g
  27. 27 * Input          : None
    ' F8 J9 l6 u! p; ^6 w, B
  28. 28 * Output         : None
    ! s1 R7 R/ z& }& C3 {$ g7 ?
  29. 29 * Return         : None
    9 o) s7 M* p1 o+ d9 `; n
  30. 30 *******************************************************************************/9 n4 ]5 t$ o$ E4 S: ?
  31. 31 / n3 d; s& v; ?# [. u: g- G
  32. 32 #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)
    ; n+ h: W6 w" T( M! H+ d
  33. 33 void USB_FS_WKUP_IRQHandler(void)" z5 ]+ O6 B' b% u5 e8 @
  34. 34 #else% c% c4 k+ U. S7 K
  35. 35 void USBWakeUp_IRQHandler(void)
    3 Q/ @. J+ D  W5 s' a
  36. 36 #endif
    % z( n9 q4 m) r: |5 Q9 [
  37. 37 {
    1 U! H2 `2 g6 v
  38. 38   EXTI_ClearITPendingBit(EXTI_Line18);
    " L- K( K" H4 \) Q4 S% ]& ~
  39. 39 }
复制代码
0 S1 W% S# ~5 k* v& a
2,修改代码hw_config.c删除无用代码,新建立2组,读FIFO和写FIFO的函数。后面会用到。
代码如下:
代码2
  1.   1 /* Includes ------------------------------------------------------------------*/
    4 ^5 W# U1 J8 E. \$ t: q% X; @$ R
  2.   2
    ( h3 c6 z9 b" e$ I
  3.   3 #include "usb_lib.h"
    2 Q3 `( I! V! B
  4.   4 #include "usb_prop.h"
    & |  k" \$ j* y& I; |9 F1 ?
  5.   5 #include "usb_desc.h"0 A% c, Y" h: m/ E
  6.   6 #include "hw_config.h": R8 l! P* ~- ]6 w+ |
  7.   7 #include "usb_pwr.h"$ ~& v* M' a, b  f9 ?  ^- S  k1 b
  8.   8 #include "Queue.h"
    & P( o2 N# k3 w6 Q
  9.   9 , C  X  A  ]6 {/ e) t6 O% T* K8 H
  10. 10
    2 }6 ~+ a9 t$ F! m, i$ _
  11. 11 /* Private typedef -----------------------------------------------------------*/
    ; t% ~2 j% \  y0 h5 `2 p8 h
  12. 12 /* Private define ------------------------------------------------------------*/
    6 M7 W/ p( v  b: i  Q- t' b9 O; Z
  13. 13 /* Private macro -------------------------------------------------------------*/0 a: i% f: b& g6 g' f
  14. 14 /* Private variables ---------------------------------------------------------*/
    ' ^& }1 W# d3 B8 p& ]
  15. 15 ErrorStatus HSEStartUpStatus;& z/ ]7 h! R. c7 ?
  16. 16 USART_InitTypeDef USART_InitStructure;0 D) S6 L! S7 x( E
  17. 17 EXTI_InitTypeDef EXTI_InitStructure;
    # c( K5 R! R8 e' u& @! i
  18. 18 9 p0 |6 C% j' G' N: T7 T
  19. 19
    0 e9 Q$ {0 a$ I5 K4 h2 w; ]" g/ ?
  20. 20 #define USB_COM_RX_BUF_SIZE         (1024 + 256)
    ) @9 Z/ g5 C' L) [; V
  21. 21 #define USB_COM_TX_BUF_SIZE         (1024 + 256)
    3 o, ^8 p6 J2 }( S& }- N# v
  22. 22
    / }) ^/ j6 E( e& ~) w6 u
  23. 23 static QUEUE8_t m_QueueUsbComRx         = {0};
    5 k! {9 f' ]: ?
  24. 24 static QUEUE8_t m_QueueUsbComTx         = {0};
    # C$ H+ W/ n: ^
  25. 25 static uint8_t  m_UsbComRxBuf[USB_COM_RX_BUF_SIZE]      = {0};     
      v6 u5 Q/ d# ~6 H1 G  u
  26. 26 static uint8_t  m_UsbComTxBuf[USB_COM_TX_BUF_SIZE]      = {0};   2 _: z" v  x% J' t$ x5 u" `
  27. 27   n) }4 P$ {6 b" L
  28. 28 static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);
    7 @' I9 s* i$ F; B0 d. C
  29. 29 /* Extern variables ----------------------------------------------------------*/" A% N' y3 @8 F) I
  30. 30 4 Z- V: g/ A& w0 V
  31. 31 extern LINE_CODING linecoding;
    - C) ?; U! q, {5 {
  32. 32 5 J' [: z8 `) M4 y0 R
  33. 33 /* Private function prototypes -----------------------------------------------*/
    ' z* H" ~' k* \
  34. 34 /* Private functions ---------------------------------------------------------*/
    5 P% a4 O0 y+ }; {
  35. 35 /*******************************************************************************
    ; U4 D) _/ q) Q7 R1 Y# _: H" @, |- A
  36. 36 * Function Name  : Set_System
    ! Q/ k8 B4 U& a0 J  K4 Y% Z
  37. 37 * Description    : Configures Main system clocks & power5 x4 K( m; [' A( }
  38. 38 * Input          : None.
    ! l' b/ m) n; E
  39. 39 * Return         : None.) T( m/ ?1 z) V8 [1 p
  40. 40 *******************************************************************************/  e1 w/ l1 d' d. e9 z
  41. 41 void Set_System(void)
    * K" R# u& g% a
  42. 42 {- y& N/ U/ J0 u: t: e6 `- P
  43. 43   GPIO_InitTypeDef GPIO_InitStructure;
    ( Q1 @6 b7 Q& g8 W, s. L9 H
  44. 44
    ! W$ W& D% _1 x" e, o
  45. 45   QUEUE_PacketCreate(&m_QueueUsbComRx, m_UsbComRxBuf, sizeof(m_UsbComRxBuf));7 O# c; C  b1 V3 ~
  46. 46   QUEUE_PacketCreate(&m_QueueUsbComTx, m_UsbComTxBuf, sizeof(m_UsbComTxBuf));
    6 u5 u" M) `. d9 w4 w9 m
  47. 47   
    7 Y* \9 W1 X; _
  48. 48   /* Enable USB_DISCONNECT GPIO clock */
    6 p% `0 t) O& Y0 G  I( v
  49. 49   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);
    ! L3 t9 Z, F( ^' k, `
  50. 50 9 z. Q& l7 D+ E6 D$ s
  51. 51   /* Configure USB pull-up pin */
    8 w- p1 |9 k) q' {/ |# Z2 c) L% Z
  52. 52   GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN;' z$ d4 p( @, _" F
  53. 53   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    % m0 h: m8 k4 B! i2 e8 T$ K  u
  54. 54   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;2 }/ F, t  v" G, E/ U% B( u7 {" S
  55. 55   GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);
    9 K0 z% Q4 u3 ]7 o6 a5 l' J! E
  56. 56   
    ! n. x# l5 ^5 l
  57. 57   /* Configure the EXTI line 18 connected internally to the USB IP */$ h  c" x0 ?  d( J
  58. 58   EXTI_ClearITPendingBit(EXTI_Line18);! p" |7 d( m7 U% o* _& `
  59. 59   EXTI_InitStructure.EXTI_Line = EXTI_Line18; , o' m/ M4 s2 e0 {. z! r8 v' b' r
  60. 60   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;$ E( S. o+ ~) L4 p4 U6 P
  61. 61   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    - d* x7 u: b! S( z" K
  62. 62   EXTI_Init(&EXTI_InitStructure);/ ]9 Q- ^& V6 N4 Q" Q3 I5 E
  63. 63 1 d( [% F3 I% E
  64. 64   
    6 T. S5 X. u9 }4 F2 n- P
  65. 65 }0 T3 H  _* _7 J1 D1 A$ u
  66. 66 8 ~  w% H6 M0 v+ r" N
  67. 67 /*******************************************************************************
    * h# [4 ~1 |, C1 V9 J; B# b
  68. 68 * Function Name  : Set_USBClock+ O& x! l' g8 D; B/ e2 _
  69. 69 * Description    : Configures USB Clock input (48MHz)
    ! [8 Z/ u/ m! R) L0 `' t% A* M! l
  70. 70 * Input          : None.
      d. X# R* ~- ^, o
  71. 71 * Return         : None.
    ! ~" p+ c: ^' C8 ], a) ?
  72. 72 *******************************************************************************/
    % T+ O1 h6 U0 Q# _# b! D! Z
  73. 73 void Set_USBClock(void)5 P' R, R8 k. ~: ~9 J
  74. 74 {
    : b  Z+ y- E. l# k3 m+ |1 v
  75. 75   /* Select USBCLK source */
    ( x) T. W( d* k& x+ V
  76. 76   RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);4 |- W  J" w8 x9 j
  77. 77   & M0 V5 ]6 J! e& e
  78. 78   /* Enable the USB clock */) v* T1 g( o# e4 [
  79. 79   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);( s7 ^  D$ L8 \1 D* u
  80. 80 }" `/ u+ ^( t' Y6 h" j& j
  81. 81 5 c$ w$ g1 e; i0 w) u
  82. 82 /*******************************************************************************$ g$ Y3 o  W# h( q: I
  83. 83 * Function Name  : Enter_LowPowerMode# ?2 J+ X" E# B8 H: k
  84. 84 * Description    : Power-off system clocks and power while entering suspend mode  i: M, z' _/ h3 n! R+ E
  85. 85 * Input          : None.
    4 C+ q: O0 }& ]/ E
  86. 86 * Return         : None.
    ' r3 ^4 N# g, D! t& q
  87. 87 *******************************************************************************/# M/ h6 ^5 N- \
  88. 88 void Enter_LowPowerMode(void)
    " C) n% k" y* a7 o+ Q
  89. 89 {" j6 a: u# N0 x% F
  90. 90   /* Set the device state to suspend */# A5 k5 a" `2 n. s! l* @
  91. 91   bDeviceState = SUSPENDED;4 B( `0 q4 n& T- H
  92. 92 }5 B. D! U4 t+ m, y
  93. 93 6 j; v+ j& c. r6 s& b9 N
  94. 94 /*******************************************************************************
    $ v* t2 j& \) I1 I* b1 v
  95. 95 * Function Name  : Leave_LowPowerMode+ \5 b. d6 ^; c8 Q2 ~
  96. 96 * Description    : Restores system clocks and power while exiting suspend mode/ {$ b# O/ g1 D9 {/ z. B
  97. 97 * Input          : None.
    / L4 u2 D! d" i1 |
  98. 98 * Return         : None., @. ]+ M; w3 w% R5 b9 V  i8 F* C
  99. 99 *******************************************************************************/
    . ?, u* o6 H( y0 f1 I
  100. 100 void Leave_LowPowerMode(void)
    4 A7 _1 n; n( H0 r; q4 e* y
  101. 101 {
    # W$ K( P" v3 P+ {+ q, {& f
  102. 102   DEVICE_INFO *pInfo = &Device_Info;
    % G5 P- Q, ]- k  t; f0 R
  103. 103 0 x; l; j5 \/ [% T, _/ f
  104. 104   /* Set the device state to the correct state */) {; k" r9 O5 C0 Y
  105. 105   if (pInfo->Current_Configuration != 0)
    " l1 L( q9 ~0 k* x  j. ?$ D8 W. P
  106. 106   {
      _& ~8 ~# W+ [* ^$ G
  107. 107     /* Device configured */9 F# a6 k7 [5 N  d6 ]
  108. 108     bDeviceState = CONFIGURED;" C) z: y8 T2 ]( S& ^  i
  109. 109   }
    8 T5 G# F' q1 {; s; L9 W
  110. 110   else; p$ @! T9 @( ^4 M) m
  111. 111   {1 l+ P, f% F1 q2 C3 v- [
  112. 112     bDeviceState = ATTACHED;& }3 Q! F5 p# x, J2 r: z" r
  113. 113   }$ R, Y5 N/ \0 {! V; z) {
  114. 114   /*Enable SystemCoreClock*/, y+ Q8 ?- ~. i$ |' `9 O) N) q, `
  115. 115 //  SystemInit();" q7 d" Y, E' {, y( [
  116. 116 }. \: b0 u3 l( ~" m# @; _! n
  117. 117 , O$ _1 k; X! A' q
  118. 118 /*******************************************************************************7 ?0 X. s! P8 u% @
  119. 119 * Function Name  : USB_Interrupts_Config
    $ K2 c6 \0 s5 w# O; a0 y  U+ X
  120. 120 * Description    : Configures the USB interrupts% Q! S+ I, ^( l" e" G- C
  121. 121 * Input          : None.  W6 r9 Q+ `. N- V- z7 G# u
  122. 122 * Return         : None." u+ L2 l9 o$ a3 E6 w7 v; X: p
  123. 123 *******************************************************************************/% `0 \) c7 V: x  }4 b' O
  124. 124 void USB_Interrupts_Config(void)# H+ p3 w7 }) F2 H  }
  125. 125 {2 ]" @7 c6 Y6 _8 `% b1 N
  126. 126   NVIC_InitTypeDef NVIC_InitStructure; ' r) q7 C! {4 |
  127. 127
    ! [4 K0 _8 t. h& r0 x2 p8 f3 x
  128. 128   NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;( }  K3 q8 J2 y  w8 V6 O: t
  129. 129   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;$ _/ Y1 M; @+ b, w5 v; i$ N
  130. 130   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    , }: z0 }/ T6 A7 n
  131. 131   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    7 q. z3 v4 q8 C
  132. 132   NVIC_Init(&NVIC_InitStructure);
    3 d! K& [& r( k( @3 I
  133. 133   ; F" h/ q$ k+ T2 p% Y. h3 N
  134. 134     /* Enable the USB Wake-up interrupt */
    * }+ H9 q. }: ~4 R
  135. 135   NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
    2 B) K; G* M- o% h2 q
  136. 136   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;/ r' A% k) Z2 ~" P- e- U
  137. 137   NVIC_Init(&NVIC_InitStructure);
    ' S( N' n/ l( i# W- X8 c
  138. 138 }3 O0 {4 H) J# n' N/ x
  139. 139 . ]1 ?3 P% Q; a8 b/ Z" I
  140. 140 /*******************************************************************************
    ; K( y# L: z9 }( f2 c
  141. 141 * Function Name  : USB_Cable_Config
    % I, i& t! v% X3 r' W# [3 D
  142. 142 * Description    : Software Connection/Disconnection of USB Cable( g6 B# U  a2 _0 P9 ]
  143. 143 * Input          : None.
    ; P  q/ |" i# T& C8 r2 P( {+ `9 Z
  144. 144 * Return         : Status
    $ d% Q) j" ~4 W2 b& W3 s" R
  145. 145 *******************************************************************************/
    # r" R6 e: n# ?- Q) l& j0 G6 t5 Q: }
  146. 146 void USB_Cable_Config (FunctionalState NewState)
    $ Y3 V( j. @9 D
  147. 147 {# {" e5 K& _* c  m; @% x
  148. 148   if (NewState == DISABLE)
    - w+ l* U$ H, F
  149. 149   {
    % M0 _# _. Y/ O+ d
  150. 150     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);7 E( a- R2 e7 d! H! U9 z
  151. 151   }* e% H& f( S6 u1 {
  152. 152   else
    $ x2 U; Y$ a1 z8 z$ b* B
  153. 153   {' [& J7 Z+ v! C
  154. 154     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);/ t: u' J( O1 y
  155. 155   }
    9 R5 r& l6 l! G2 l9 n
  156. 156 }  I8 K- t$ M& e
  157. 157 $ n4 ]) l! S( C* d. I! \
  158. 158 /*******************************************************************************4 [4 V/ x2 U* I/ V6 u% o
  159. 159 * Function Name : void USB_Config(void)! {# v% @: Z9 z; S& f+ b
  160. 160 * Description   : USB系统初始化
    ( ^5 k. X, d% K/ g! W: L
  161. 161 * Input         :
    ' p" J- O7 c7 ]% _& h0 E
  162. 162 * Output        : . C- I6 m! X  I4 H
  163. 163 * Other         :
    4 m( h, v7 [( o) E! t' Y: O
  164. 164 * Date          : 2014.11.28  q& ]# p8 S+ w  ^5 U! H! A2 I
  165. 165 *******************************************************************************/9 g/ G( a& \, b
  166. 166 void USB_Config(void)
    0 P/ v3 c- D. d& G6 H% |
  167. 167 {
    & z. E/ o4 S" H( ?4 _
  168. 168     Set_System();
    1 P9 ?* }& o) e4 {% e  L
  169. 169 9 S, y9 N* u9 x4 t& R
  170. 170     Set_USBClock();
    9 T. h  f* @; Z+ f
  171. 171
    7 S3 b0 k) o$ v2 p4 V; D( O
  172. 172     USB_Interrupts_Config();: K. g  h/ H  e0 d. G
  173. 173 8 l7 o2 g8 Y2 R; z+ X9 X/ e0 k
  174. 174     USB_Init();
    * E% X: r" a" [5 ~
  175. 175 }$ r. e+ J- k+ f, \  p# W8 U
  176. 176 - X0 K& Q% g. K2 r
  177. 177 /*******************************************************************************+ P& F: q2 @0 v1 _4 q
  178. 178 * Function Name : uint32_t USB_RxRead(uint8_t *buffter, uint32_t buffterSize)
    3 X) @0 S4 c9 D" ?* \4 F
  179. 179 * Description   : 从USB接收缓存中读数据1 t* v& f. B7 D# |. w
  180. 180 * Input         : ' U  z3 F1 X# a2 ~3 ^
  181. 181 * Output        :
    5 y* B0 z) N' G* x: F9 Y8 \! \0 U
  182. 182 * Other         : 8 T! t+ w5 z' L
  183. 183 * Date          : 2014.11.28
    + n, ~% t# }$ |5 r0 g  p" y( v5 H
  184. 184 *******************************************************************************/+ O' e/ o. y# q: [7 x
  185. 185 uint32_t USB_RxRead(uint8_t *buffter, uint32_t buffterSize)8 I: _( s0 A% A& x9 l$ Y/ [
  186. 186 {
    ! c  D. ~) b: i. G
  187. 187     return QUEUE_PacketOut(&m_QueueUsbComRx, buffter, buffterSize);6 u. G  ~% {2 B4 w5 ?5 g
  188. 188 }
    * }: `6 Y6 u$ O+ k1 ^/ U
  189. 189 /*******************************************************************************
    4 w; F: J+ f, x5 E, ^3 O
  190. 190 * Function Name : uint32_t USB_RxWrite(uint8_t *buffter, uint32_t writeLen); d) l/ d, D& s
  191. 191 * Description   : 写数据到USB接收缓存中6 i+ J5 N# W( z/ s! _4 t7 d
  192. 192 * Input         :
    % l6 ]# H3 K; [$ L, J1 o
  193. 193 * Output        : * @$ z* v3 \; o7 t, I1 s0 s
  194. 194 * Other         :
    ! k9 z, o: h* }) p
  195. 195 * Date          : 2014.11.28  d0 T% v3 F7 R
  196. 196 *******************************************************************************/
    5 Q) h9 w( P8 J% k. Q
  197. 197 uint32_t USB_RxWrite(uint8_t *buffter, uint32_t writeLen)5 x; _1 l2 ?! X( w9 y
  198. 198 {& n$ l+ Z, }9 o+ n7 h: V
  199. 199     return QUEUE_PacketIn(&m_QueueUsbComRx, buffter, writeLen);
    & x" H' ]5 z. f' W1 C) ^- q
  200. 200 }
    & x( W  K3 ^) W5 y3 d
  201. 201 /*******************************************************************************
      p4 ^+ m" O9 k$ p$ l
  202. 202 * Function Name : uint32_t USB_TxRead(uint8_t *buffter, uint32_t buffterSize)
    , ]! c. \, }" V
  203. 203 * Description   : 从USB发送缓存中读数据
    0 f# c* b& l8 Y+ a, o$ w
  204. 204 * Input         : 2 |2 G# j) R, a' R! O
  205. 205 * Output        :
    8 r2 g; m/ T) y2 O/ u
  206. 206 * Other         :
    " h& ?4 O9 f; i$ c! q/ U
  207. 207 * Date          : 2014.11.28  O2 A; Y+ K. y& K3 W, k, k
  208. 208 *******************************************************************************/
    ' K# h( w2 m7 t
  209. 209 uint32_t USB_TxRead(uint8_t *buffter, uint32_t buffterSize)
    - u6 A: s# u' b/ \
  210. 210 {
    . W' X$ V4 H- x5 Z3 {( ^
  211. 211     return QUEUE_PacketOut(&m_QueueUsbComTx, buffter, buffterSize);;5 X! M4 b  S7 L" g- t6 I9 a* P
  212. 212 }
    7 y; }5 V% Q. i2 v( F  {3 o
  213. 213 /*******************************************************************************
    / F/ Z8 }1 D+ x$ Z" n/ o" z# V$ c% L
  214. 214 * Function Name : uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)
    : j: l$ V& t" l, S& q
  215. 215 * Description   : 写数据到USB发送缓存中
    : m2 e) O/ c  u1 [9 P( q% H
  216. 216 * Input         :
    + k; t, t) H9 P  X
  217. 217 * Output        : & d0 M# Z7 h& m2 I3 G& E  }3 y
  218. 218 * Other         : 9 i' o; H6 [9 p5 i/ C& H
  219. 219 * Date          : 2014.11.28
    4 \0 [- P9 b" m, n
  220. 220 *******************************************************************************/4 {1 m. v0 F9 e/ N9 Q8 M! ~
  221. 221 uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)
    " j0 N# X7 f4 M% f
  222. 222 {& J8 Y& I0 c8 p: s
  223. 223     return QUEUE_PacketIn(&m_QueueUsbComTx, buffter, writeLen);" p; N/ }1 L' J+ y
  224. 224 }6 b% T, r& J+ E; f
  225. 225 + @3 u( x: L5 ?* B% {
  226. 226
    / P" F) N: B) ], e1 J0 {* ?. m
  227. 227
    9 A: [1 m$ |; [; [
  228. 228 /*******************************************************************************( x/ x' q$ P# Y
  229. 229 * Function Name  : Get_SerialNum.
    - M5 R- [! X/ N% D+ F, O% h
  230. 230 * Description    : Create the serial number string descriptor.
    " u1 l* R5 I- r) P5 r) U
  231. 231 * Input          : None.
    7 ]6 Z3 o% ^9 b$ `% p* _1 `
  232. 232 * Output         : None.* k4 W0 Z7 U  z1 q; g+ F" |
  233. 233 * Return         : None.# w: u1 W) D2 [8 t" U. M
  234. 234 *******************************************************************************/& l8 ^& n) |* z$ D$ N6 t( d
  235. 235 void Get_SerialNum(void): S5 j/ y: f) I9 y3 z! X/ o# v5 m, |
  236. 236 {+ R, r( U; B- e2 I/ y: k
  237. 237   uint32_t Device_Serial0, Device_Serial1, Device_Serial2;' I, i, M! A! e2 ?0 u7 j6 S1 ?, z  a& `
  238. 238
    , ^+ B  {, c0 X' E! n7 X; c$ q
  239. 239   Device_Serial0 = *(uint32_t*)ID1;
    , a4 b) r1 d: J8 k' m3 J
  240. 240   Device_Serial1 = *(uint32_t*)ID2;
    ' O( C( R! M5 X1 W
  241. 241   Device_Serial2 = *(uint32_t*)ID3;  1 J, f; Q9 i' p
  242. 242
    ' l9 a) }9 B5 f0 g
  243. 243   Device_Serial0 += Device_Serial2;
    ( E9 u* W. t' Y/ `+ f
  244. 244
    1 u- L0 B. i, v' p4 P! L' c
  245. 245   if (Device_Serial0 != 0)1 X- A; G5 c: U# C! q7 t: a
  246. 246   {
    7 d! ?1 S% L3 ~, O% F( X
  247. 247     IntToUnicode (Device_Serial0, &Virtual_Com_Port_StringSerial[2] , 8);, a7 o4 ?* @8 T0 ^8 r0 |  x5 W
  248. 248     IntToUnicode (Device_Serial1, &Virtual_Com_Port_StringSerial[18], 4);
    6 a8 S% B7 y1 K$ L
  249. 249   }
    9 X% g3 R0 J* j0 U5 ~5 I- T
  250. 250 }
    8 b" f+ \/ F0 G) P& B) F
  251. 251 & u3 o: Q& n: O' W+ S
  252. 252 /*******************************************************************************8 p1 J4 N, H$ R- Y. o/ f
  253. 253 * Function Name  : HexToChar.  A& E4 a7 X" G, v: }7 S& ^
  254. 254 * Description    : Convert Hex 32Bits value into char.0 \2 K, E- x% [! Q* k- J- p
  255. 255 * Input          : None.
    ( M1 \- z4 @& b/ i* @( B9 H2 V9 o
  256. 256 * Output         : None.
    / R# p+ F' L  _2 s# O- P6 r* n' k
  257. 257 * Return         : None.
    1 J0 I5 {- d% l: U2 e. `% e( d, Q
  258. 258 *******************************************************************************/
    + V# E& f+ T4 R
  259. 259 static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)0 @& y; u/ A3 X: G
  260. 260 {
    - U  T& ?& Z& P( k$ M2 N% p
  261. 261   uint8_t idx = 0;: E$ A  n: Q7 G9 V( h: u
  262. 262   
    2 s; {" a( m; R/ J
  263. 263   for( idx = 0 ; idx < len ; idx ++)% Q4 Z4 v3 x( l
  264. 264   {
    4 s( B7 P7 w) m& a' }, [  U
  265. 265     if( ((value >> 28)) < 0xA ), _& s: U- j0 ~
  266. 266     {
    - Q2 V& ^: x. v! e! d" q" k! S
  267. 267       pbuf[ 2* idx] = (value >> 28) + '0';# ^3 L3 \! y& m; `; N" S& m
  268. 268     }
    8 u- B1 }0 f8 A" U, f7 w1 C
  269. 269     else$ }/ r* ]$ e9 {2 o/ g; u, v
  270. 270     {2 Q' A/ P+ N" w5 o: K  ~! s7 C
  271. 271       pbuf[2* idx] = (value >> 28) + 'A' - 10; / p- e* w& Y: l
  272. 272     }* X% p& C, [9 d/ [, K6 ^% G
  273. 273     
    ) d, u$ _5 n+ ]; L1 [
  274. 274     value = value << 4;
    0 j- h9 ?9 K1 C# Y: T
  275. 275     9 j8 [+ I  n. u; v  N, K% J
  276. 276     pbuf[ 2* idx + 1] = 0;1 p! G* @+ X) i6 ?* G5 j0 S
  277. 277   }
    9 u  `  V* i8 {. w; O
  278. 278 }* p5 }" g1 w% N
  279. 279 6 j& o9 w! y0 ^( ~7 N
  280. 280 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码
6 z, ^. t& q9 w# p* c+ Q5 V

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

: T+ C/ ]" U0 B; X: A2 Y& c) n
300038465597900.jpg

3 [- x5 m3 d: d  }8 h3 l( x
关于USB口使能控制引脚,需要根据开发板的引脚定义来修改宏定义platform_config.h文件中,笔者使用的是神舟3号开发板,控制信号刚好和demo相反,所以修改hw_config.c代码如下:
代码3
  1. 1 /*******************************************************************************
    2 B- O. F: k& T) T2 C2 e4 j9 S
  2. 2 * Function Name  : USB_Cable_Config
    " V8 O! P. S  L) T; D, p: ?
  3. 3 * Description    : Software Connection/Disconnection of USB Cable, r  t: }. V: U  L9 y
  4. 4 * Input          : None.2 S4 D+ t" r* ]* a0 W% k7 @
  5. 5 * Return         : Status
    6 i4 [* x& D7 f: ]- m
  6. 6 *******************************************************************************/
      d5 k# a2 W5 g) T
  7. 7 void USB_Cable_Config (FunctionalState NewState)
    ' K6 I4 p0 s2 e! u% {+ s
  8. 8 {+ C0 f% R0 \3 m8 J1 s
  9. 9   if (NewState == DISABLE)
    4 W* G9 I! b+ q; R0 A# N4 B
  10. 10   {* f1 k/ w3 P! S8 @$ y/ y
  11. 11     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);6 B9 _5 O6 k6 X5 _6 Y
  12. 12   }( f/ p+ S: n" o" R6 ?: l# n) G0 i
  13. 13   else' k" n7 M6 M$ }; C
  14. 14   {
    3 Q, u" `( ?8 q" }; a# Q( p4 J. p
  15. 15     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    4 Q0 T6 Z% Q) j8 x
  16. 16   }
    1 h2 ?& ?% Q& v0 G
  17. 17 }
复制代码

9 t* s4 y+ t0 t, L
3,现在修改USB 回调函数中的代码usb_endp.c文件。使用下文代码替换:
代码4
  1.   1 /* Includes ------------------------------------------------------------------*/0 s, I( K; g3 g0 s) c- }. ]8 k
  2.   2 #include "usb_lib.h"+ H! `4 ~4 M5 q( {- C+ K5 y# ]# t
  3.   3 #include "usb_desc.h"
    ( e& e/ i5 X" f, t
  4.   4 #include "usb_mem.h"
    ' i: D$ D. W& X  V
  5.   5 #include "hw_config.h"
    8 p. w' Q7 s- w, c1 Y! O
  6.   6 #include "usb_istr.h"
    * e6 v3 b7 G2 I: ^% |. ~
  7.   7 #include "usb_pwr.h"
    6 E$ Z$ R) t$ q+ s& ^. C+ d
  8.   8
    0 z3 Y+ t' ^9 }6 K  J  b
  9.   9 /* Private typedef -----------------------------------------------------------*/- E3 ]) [$ |6 g3 H
  10. 10 /* Private define ------------------------------------------------------------*/
    , d8 p# F: n& ~- x5 a+ m  h  v# _
  11. 11 3 H: {) z* w+ b' P- k" j$ [( A. u
  12. 12 /* Interval between sending IN packets in frame number (1 frame = 1ms) */
    # M  i9 U- M2 }6 p2 x/ P" ], {: p
  13. 13 #define VCOMPORT_IN_FRAME_INTERVAL             5/ V, J% O9 v. Z/ Q, v& g+ d6 p
  14. 14 4 X; Q+ J7 |0 U& A) y$ }
  15. 15 /* Private macro -------------------------------------------------------------*/
    ! X5 G% ^/ a4 c
  16. 16 /* Private variables ---------------------------------------------------------*/
    # p, O8 f. J# ]$ z2 {
  17. 17 static uint8_t txBuffter[VIRTUAL_COM_PORT_DATA_SIZE] = {0};' t: p5 m$ X# z5 V1 N2 L. b
  18. 18 static volatile uint8_t txFlg = 0;
    , y1 e8 q1 S7 c9 h% ?  y
  19. 19 static volatile uint32_t FrameCount = 0;
    6 e9 |7 y1 \  i, \  ]/ I/ [; @" G2 Y
  20. 20
    9 I2 O- }+ J7 Q2 M- t. G
  21. 21
    . V. E2 `* j7 [, @
  22. 22 /* Private function prototypes -----------------------------------------------*/7 E  J3 p* o' v+ z
  23. 23 /* Private functions ---------------------------------------------------------*/
    2 [5 L' \( r% g6 u1 K( @2 D
  24. 24
    * b( V4 k1 h/ W% I+ b  T8 _
  25. 25 /*******************************************************************************3 H9 r7 m. O& |7 N  ]5 W# s( p
  26. 26 * Function Name  : EP1_IN_Callback
    ; c4 c6 e( w& L6 r3 z8 T5 r
  27. 27 * Description    :
      G4 I. t$ M; m: H* E# V" ^/ p
  28. 28 * Input          : None.
    + i+ D- C- U- i8 w; B: c1 H/ Q+ v
  29. 29 * Output         : None.
    ; }( l$ v# f$ l' r4 J
  30. 30 * Return         : None.
    4 H7 n3 R# b1 s3 |: I( T5 n
  31. 31 *******************************************************************************/$ K# X9 A& u6 D$ L! t2 p
  32. 32 void EP1_IN_Callback (void)/ N0 s% c2 B: U2 S* y; ~" u
  33. 33 {5 o, J9 ~% k1 l* j% a+ v
  34. 34     uint16_t len = 0;
    $ Q2 r; ]( Q  M' `9 H! _6 u$ E2 @
  35. 35     
    9 F0 U" D6 z5 h) Q/ K3 d9 b
  36. 36     if (1 == txFlg). j9 @  d9 A/ p; E
  37. 37     {4 i) L) T, ~6 ]: {2 g% {
  38. 38         len = USB_TxRead(txBuffter, sizeof(txBuffter));2 J$ v" G# \6 u9 a7 M8 g
  39. 39 & c7 C4 r& w2 V# C
  40. 40         if (len > 0)
    ' Y6 D1 p. d: r9 g3 @4 z$ j
  41. 41         {) B. O+ j1 z8 \  f* F
  42. 42             UserToPMABufferCopy(txBuffter, ENDP1_TXADDR, len);
    6 x! m7 _! [6 r: Y/ x$ _9 A& a& {0 p
  43. 43             SetEPTxCount(ENDP1, len);
    : M, T% P( S# `
  44. 44             SetEPTxValid(ENDP1);
    3 c+ k/ T5 K6 Y( {2 d: J1 C
  45. 45             FrameCount = 0;+ R4 g, z* N. g) c8 z
  46. 46         }, h/ t8 Z* V) f, ^6 Q+ N% s, m* [
  47. 47         else
    * E/ i: n( |3 L
  48. 48         {
    $ W  `' o2 N4 n& ~
  49. 49             txFlg = 0;- I$ N* e! @$ j/ \: O! z$ T
  50. 50         }
    7 Q% J7 F( y2 Q: ^
  51. 51     }3 `: F& R. x, y* {! O3 h3 {8 K: Q
  52. 52 }9 h8 s, E' \7 [& O
  53. 53
    6 c: c2 G. v4 O7 `* F  w
  54. 54 /*******************************************************************************+ }5 D9 Z! _+ p. p
  55. 55 * Function Name  : EP3_OUT_Callback
    ) g9 K3 W, e" h
  56. 56 * Description    :& J: J- S  p  I8 N7 K- D
  57. 57 * Input          : None.
    . T# g  n2 w0 I, ^
  58. 58 * Output         : None.
    4 J" C4 A6 B: h% y
  59. 59 * Return         : None.- g5 h. p: x: h% q4 B6 N, X
  60. 60 *******************************************************************************/1 y/ |) i. T; Q9 C. t
  61. 61 void EP3_OUT_Callback(void)
    : G# T; @" _) M0 s
  62. 62 {' N% F& \) x* y  ?- \5 |3 k
  63. 63   static uint8_t buffter[VIRTUAL_COM_PORT_DATA_SIZE] = {0};* F& J3 |& }3 l, h
  64. 64
    ' Q% i- [, @- z" W* |' r! [
  65. 65   uint16_t USB_Rx_Cnt;
    + v/ h) ]$ B5 j. M
  66. 66   
    ! _* o8 U9 }; F* U
  67. 67   /* Get the received data buffer and update the counter */
    . M3 ?! ^/ n* Q3 M, p; O
  68. 68   USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, buffter);
    ! C) }- @6 z$ ~9 b% \, F2 r5 A
  69. 69   : Q/ w( ~5 z8 R+ R, [2 X
  70. 70   /* USB data will be immediately processed, this allow next USB traffic being
    2 {9 \4 D) ?; k
  71. 71   NAKed till the end of the USART Xfer */
    ! i  t3 l- t- O; R
  72. 72   USB_RxWrite(buffter, USB_Rx_Cnt);4 M: x! V2 @$ r2 k+ R& \- d& W5 N
  73. 73 # M4 Q- O: F8 P
  74. 74   /* Enable the receive of data on EP3 */
    ; a, i# n  O4 D' Q+ H
  75. 75   SetEPRxValid(ENDP3);
    0 [' P- S8 Q$ g9 D/ N4 |" Z9 Q4 f9 k
  76. 76
    : O) _9 d/ S9 D$ L
  77. 77 }
      N% T# ]+ Y- Y6 |
  78. 78
      ~% j. r, y& e3 X- \
  79. 79
    ! W5 f9 O* b8 x
  80. 80 /*******************************************************************************# {& Z! ^7 F4 l5 s+ o: i0 F$ `
  81. 81 * Function Name  : SOF_Callback / INTR_SOFINTR_Callback: \5 e5 o2 h3 C% J: x4 L
  82. 82 * Description    :
    : p+ T" A: r. U  S* _
  83. 83 * Input          : None.* h5 D1 ]) O$ C
  84. 84 * Output         : None./ S' ]* ]$ j5 K9 U) J/ [  L. l
  85. 85 * Return         : None.
    " y+ w' B. H. \0 ]
  86. 86 *******************************************************************************/7 V3 ^# B+ R: S. ~
  87. 87 void SOF_Callback(void)+ ?  K% q  ^2 [; n: o8 ?
  88. 88 {3 v$ ]  T7 O0 \0 @5 P& {7 D/ i2 R6 Q
  89. 89     uint16_t len = 0;5 O: l! z' y: [! |( v5 v
  90. 90 5 C" U9 g" }) n3 U! s# f
  91. 91     if(bDeviceState == CONFIGURED), Y+ u4 [! Y6 D4 d8 Z2 q
  92. 92     {7 m. f% y" [- }  G! l' N
  93. 93         if (0 == txFlg)
    3 t/ H1 r" I. r( x6 r
  94. 94         {
    / T* t' Y7 e# |3 ?/ E
  95. 95             if (FrameCount++ == VCOMPORT_IN_FRAME_INTERVAL)1 m5 H0 S5 L# N1 s
  96. 96             {
    0 o' q' c: D6 O* Y' |
  97. 97                 /* Reset the frame counter */
    . ~! M- s: `8 V; a7 c
  98. 98                 FrameCount = 0;
    % s9 b2 I+ H1 x* I' A1 e1 l' j
  99. 99
    $ }  V5 U# v2 b# J: q
  100. 100                 /* Check the data to be sent through IN pipe */
    ( P( Z6 N' P6 Q* J. }7 e' X
  101. 101                 len = USB_TxRead(txBuffter, sizeof(txBuffter));
    3 I6 v# E2 x3 p4 \' s: R3 ~* U
  102. 102 . _! C8 P7 u# `; Y& T/ U; I
  103. 103                 if (len > 0)
    9 x% `% Z  Q: P6 G7 [" n; k
  104. 104                 {) @" K5 E$ c& s) O& O3 f
  105. 105                     UserToPMABufferCopy(txBuffter, ENDP1_TXADDR, len);
    , A0 M; @( G9 X  u; F; L
  106. 106                     SetEPTxCount(ENDP1, len);! L: U1 Z- l" ^" T: I
  107. 107                     SetEPTxValid(ENDP1);
    ! b9 Y9 Y  A0 \; @. `
  108. 108
    5 P( H% a+ b3 U5 p6 ^. s
  109. 109                     txFlg = 1;
    % S5 M6 Y3 ?2 `6 W7 o
  110. 110                 }' k! b/ K4 U  o) z
  111. 111             }8 Y; F2 m' U& M8 a
  112. 112         }
    2 e/ M* r; m# _+ g( O
  113. 113     }  
      U3 C- S, e/ h. F
  114. 114 }! }* @; {  ]# L; D7 Q1 `, @2 L4 }
  115. 115 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码
1 C" t. w6 Q; h
) y+ L) O  l/ F5 y: |
这里讲下大概意思,函数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也一起存放在上文章开始的链接中。

: [9 K4 e5 \# p
收藏 评论0 发布时间:2022-1-13 21:00

举报

0个回答

所属标签

相似分享

官网相关资源

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