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

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

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

0 t+ m5 k8 X! N' D% V3 Z( M" y: Y8 v' ~3 x& V0 ?- k1 b
首先打开官方demo我们开始进行移植,第一步复制我们可用的文件,操作如下:
Projects\Virtual_COM_Port文件夹下,复制红线部分
图1
( o& D, I7 c- `+ ^* y. w
300035032772082.jpg

- H$ R( m; ~: `9 ]4 s! w
图2
* M: h: @! q. L/ M
300035202932682.jpg
  E7 \: I# X+ @* C
我为了方便演示统放在usb/src文件夹下:
图3

7 M; m) N. K+ n% l4 W! M
300035313246246.jpg

1 o7 r: a5 x. m7 X3 @
现在复制USB的库文件,这些文件不需要我们修改:
图4

% D8 }- w! P( b& W/ Q+ n, I
300035404189967.jpg

0 s+ {$ q/ p3 e7 E  L. i
上图中的文件统一放在usb/lib文件夹下:
图5
; b$ |! Y2 Q# W  y) `* R$ ^
300036032935279.jpg

- M+ L+ }9 E: Z: W, r% G
7 s, G3 \* @! Y" a3 f
         好了现在所需要的文件我们以复制完了。这里先讲一下DEMO程序的主要工作流程:
7 M3 z/ e: O; l, Z2 a$ V, r/ o# F
300036178402768.png

% x7 r, F: H3 G! 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 ------------------------------------------------------------------*/
    2 c  x  p1 S: B" V" `
  2. 2 #include "hw_config.h"
      y& E& E! [$ U" z& n
  3. 3 #include "usb_lib.h"
    8 S, a) Y5 B, v! J8 v
  4. 4 #include "usb_istr.h"6 ]# g1 C  ?& ]2 W
  5. 5
    6 X$ Z9 o# c! f' k  \
  6. 6
    : y/ W- A( c' K- ]# ?' u3 |  s
  7. 7 /*******************************************************************************
    ; [5 e5 `$ k* q. l) Y
  8. 8 * Function Name  : USB_IRQHandler- F: s  y2 G8 n2 S' y
  9. 9 * Description    : This function handles USB Low Priority interrupts( }+ J) q' T/ E' q
  10. 10 *                  requests.
    ) x0 n9 O1 v1 e3 L- z) r" Q
  11. 11 * Input          : None/ e0 v3 z- Y% E9 c! y8 ]
  12. 12 * Output         : None4 I' P. B. r: j5 B( z. G9 C# o
  13. 13 * Return         : None
    ' L9 R5 q9 D* L1 U' l; v( @) C
  14. 14 *******************************************************************************/! s5 o# V' ^+ b; b/ U
  15. 15 #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)|| defined (STM32F37X)4 u1 H* R% _# x' m2 v! ?) |$ t
  16. 16 void USB_LP_IRQHandler(void)0 X6 l! }1 k9 E5 c) P
  17. 17 #else
    9 Q2 @( ~1 S  n* Y4 h  B4 b
  18. 18 void USB_LP_CAN1_RX0_IRQHandler(void)4 h2 j2 `0 ^1 m' B" u* q
  19. 19 #endif
    7 |7 J! ~6 Y$ `3 L5 y
  20. 20 {
      w9 `# |5 C' e" J6 Y3 {1 e
  21. 21   USB_Istr();
    5 n. o& h9 m# [$ Q- E( W- q
  22. 22 }
    % H+ Z7 ]9 d; w% ?- |) L9 [6 N
  23. 23 5 `# Q5 l2 |( T4 ~/ e
  24. 24 /*******************************************************************************
    ' w" R& w8 F, T7 [8 z. Z2 B4 \0 t, I
  25. 25 * Function Name  : USB_FS_WKUP_IRQHandler+ M7 B7 f; J3 X4 _& N
  26. 26 * Description    : This function handles USB WakeUp interrupt request.& Z# ~) e! x. x3 h& M
  27. 27 * Input          : None
    5 C- u. t. `/ W
  28. 28 * Output         : None( y$ B' F6 ~6 L4 w
  29. 29 * Return         : None
      `# ^; I6 m" }
  30. 30 *******************************************************************************/1 |+ x5 j/ k% E  I9 F- j4 D/ B
  31. 31 3 d/ i& M$ i# g! J- D2 f. y
  32. 32 #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)8 Z; g  O( v. i# _8 J
  33. 33 void USB_FS_WKUP_IRQHandler(void)
    & U; s% E3 _; _
  34. 34 #else, K5 H; s7 S* }  [  |9 w# m
  35. 35 void USBWakeUp_IRQHandler(void)
    $ G/ p% }7 x. ^9 _7 G  \
  36. 36 #endif
    ) x, i% R0 ^! [
  37. 37 {  j, a, n+ j: H5 \$ |& a% b6 m
  38. 38   EXTI_ClearITPendingBit(EXTI_Line18);' P+ d+ M" u# r% z/ U9 T, S# J
  39. 39 }
复制代码
) T# @- x! h+ s$ R' L
2,修改代码hw_config.c删除无用代码,新建立2组,读FIFO和写FIFO的函数。后面会用到。
代码如下:
代码2
  1.   1 /* Includes ------------------------------------------------------------------*/
    - I- z9 q8 m/ B( N+ e
  2.   2 " S) N  e  [+ C
  3.   3 #include "usb_lib.h"
    ) Y9 k$ C2 \4 Q* J  {' i9 R1 d; e
  4.   4 #include "usb_prop.h"
    9 Y5 S+ k* a' P+ y8 b9 d# y
  5.   5 #include "usb_desc.h"
    $ @  x4 J; u; X% S4 j
  6.   6 #include "hw_config.h"' }! Q1 H9 u/ x6 v( t+ y* r# ^
  7.   7 #include "usb_pwr.h"& R/ |& n7 z/ M( k/ A8 j- {5 i4 |  R
  8.   8 #include "Queue.h"2 h  z/ ^7 k# K& |$ w, H
  9.   9 5 M. t, B  g/ t0 }
  10. 10
    6 i5 a# V" P+ Z6 K$ B/ |
  11. 11 /* Private typedef -----------------------------------------------------------*/
    1 I5 |9 ~  b4 U0 @, ^1 e/ N& u
  12. 12 /* Private define ------------------------------------------------------------*/
    2 f( h4 M' m/ Z& a$ v
  13. 13 /* Private macro -------------------------------------------------------------*/
    5 B3 u8 n$ G! {1 c
  14. 14 /* Private variables ---------------------------------------------------------*/
    ' P- \8 P0 |$ b+ f" h8 n4 U
  15. 15 ErrorStatus HSEStartUpStatus;) A5 z- U9 V/ `$ Y* K
  16. 16 USART_InitTypeDef USART_InitStructure;
    7 e1 r+ A3 ]# B0 c
  17. 17 EXTI_InitTypeDef EXTI_InitStructure;& ]: S, ?% G4 S. f/ _2 i2 [
  18. 18
    3 I. b  V$ F& a7 E! V
  19. 19 * m4 n/ o  Z/ n, y6 G
  20. 20 #define USB_COM_RX_BUF_SIZE         (1024 + 256): I, m3 T5 {; p
  21. 21 #define USB_COM_TX_BUF_SIZE         (1024 + 256)- C# ~3 u8 s  q  {* G
  22. 22 # E: `9 Y9 m4 P
  23. 23 static QUEUE8_t m_QueueUsbComRx         = {0};
    2 v# q% V4 g! K  ~+ U% T/ l
  24. 24 static QUEUE8_t m_QueueUsbComTx         = {0};
    5 B# n; W2 q6 x: W: t4 u
  25. 25 static uint8_t  m_UsbComRxBuf[USB_COM_RX_BUF_SIZE]      = {0};     
    " `5 ~; X. U; l# u) P, k
  26. 26 static uint8_t  m_UsbComTxBuf[USB_COM_TX_BUF_SIZE]      = {0};   
    ; n) d- N: M- z
  27. 27 ) X5 f* P6 Y9 R5 i/ T, r
  28. 28 static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);
    ' l1 ^- F) X  P8 r2 ?' q- a2 [
  29. 29 /* Extern variables ----------------------------------------------------------*/. w, A# \9 _, d; C5 U- ^& n* b
  30. 30 ' B8 X" L5 R; ?3 \7 s1 S- k0 g
  31. 31 extern LINE_CODING linecoding;; s* B  B. g% M
  32. 32
    $ V' L  W6 r# a; Z% m$ D
  33. 33 /* Private function prototypes -----------------------------------------------*/1 A" f( q' G" R: S
  34. 34 /* Private functions ---------------------------------------------------------*/$ h/ b2 `% @' N9 X, e4 z% K
  35. 35 /*******************************************************************************$ r3 R4 P& q- I, Q- ?  `- J
  36. 36 * Function Name  : Set_System1 S* f1 q, k8 n" S4 {
  37. 37 * Description    : Configures Main system clocks & power
    0 P# [% Y) U( J* c4 [8 h
  38. 38 * Input          : None.
    ' K. ?  U0 s- _. H, b  L
  39. 39 * Return         : None.5 q( G; o& s7 j+ M
  40. 40 *******************************************************************************/
    ! I& y  s: J/ F- P+ y3 N- X- Y
  41. 41 void Set_System(void)
    6 u3 v! t; o* U, y8 S! r
  42. 42 {
    2 ]: Q) Z9 e) W, ]
  43. 43   GPIO_InitTypeDef GPIO_InitStructure;9 s$ w( a/ x  R$ P- r
  44. 44 0 B4 n9 d% }: X" n$ p
  45. 45   QUEUE_PacketCreate(&m_QueueUsbComRx, m_UsbComRxBuf, sizeof(m_UsbComRxBuf));
    ; C( O* e1 k6 o: {) x/ X1 c
  46. 46   QUEUE_PacketCreate(&m_QueueUsbComTx, m_UsbComTxBuf, sizeof(m_UsbComTxBuf));0 K: `9 [3 I1 [' k; \7 s
  47. 47   - J7 @6 w+ O/ v# R0 D2 l7 h
  48. 48   /* Enable USB_DISCONNECT GPIO clock */' h7 H5 K  B3 H; o
  49. 49   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);
    * g4 w3 |7 l: S
  50. 50 $ c# r, X( S1 V3 Z* B* R1 y
  51. 51   /* Configure USB pull-up pin */
    , t& b" ^8 m# d4 C( \5 u0 Q2 |
  52. 52   GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN;
    1 _6 O4 h( W) K4 t$ }
  53. 53   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    & q; _+ [6 }! b) b. @
  54. 54   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    & `2 i, t3 \' b7 N! u
  55. 55   GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);
    9 I2 ~* y4 T3 f! y- O
  56. 56   : ~% w2 B# s# ~+ ?
  57. 57   /* Configure the EXTI line 18 connected internally to the USB IP */
    ; O2 c( V( [2 u& Q+ S
  58. 58   EXTI_ClearITPendingBit(EXTI_Line18);' s0 k9 b$ ^. c3 |
  59. 59   EXTI_InitStructure.EXTI_Line = EXTI_Line18;
    : f& ?( u' y* C: [, O: E
  60. 60   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;0 E! _' l3 B0 p7 Q0 \2 S
  61. 61   EXTI_InitStructure.EXTI_LineCmd = ENABLE;- b0 s5 A/ e  v  l; X& q
  62. 62   EXTI_Init(&EXTI_InitStructure);
    / R, R. n1 o  h& u# g, D/ g, a* O
  63. 63
    % }, }0 k  f% G; Y6 }- j
  64. 64   8 p$ I& M- m# q3 h1 N- p7 Q( Z7 t; x
  65. 65 }
    + u5 p0 `  U2 ^% L; L
  66. 66 : t( ~2 I8 z# A) B  B, v* v
  67. 67 /*******************************************************************************# t% J$ X5 i/ {- H) S2 w& ~( U4 c' t
  68. 68 * Function Name  : Set_USBClock
    % t( D# b) K. ?. q; H2 ]) M2 h
  69. 69 * Description    : Configures USB Clock input (48MHz), f8 v9 m, L5 Q# u, t& P% A
  70. 70 * Input          : None.
    6 F5 V5 D' J* V3 w5 k
  71. 71 * Return         : None.
    % z+ M4 w; m" X& ~2 K
  72. 72 *******************************************************************************/) R; P7 p. t. s; @9 F. m* A( h
  73. 73 void Set_USBClock(void)) ?$ E$ V2 m: ?% `7 B
  74. 74 {
    ( [+ I6 B' a1 V- p; L
  75. 75   /* Select USBCLK source */
    ! H7 j9 i& o# O, e1 R
  76. 76   RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);( N. \) r( X3 S5 t% M' Z+ R
  77. 77   
    & s% Y, ?+ j+ Q# y( `
  78. 78   /* Enable the USB clock */! Z" t2 i4 c2 w$ T. D/ \
  79. 79   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
    ) E6 @$ I  C/ _
  80. 80 }
    ' }) l2 e: Q& V1 F$ p) s
  81. 81 ! ^! L' p- ]+ C0 n  J7 ?5 W( i
  82. 82 /*******************************************************************************. E9 ~( w+ [, H6 s9 _
  83. 83 * Function Name  : Enter_LowPowerMode( x/ {4 O% g4 \7 s" M) {2 k
  84. 84 * Description    : Power-off system clocks and power while entering suspend mode; h- {9 C9 _( s4 Y
  85. 85 * Input          : None.1 M, Q0 z; K6 {
  86. 86 * Return         : None.$ ^2 r% y/ x+ i$ r! b2 Q+ ~
  87. 87 *******************************************************************************/
    / _4 W  }# Z5 l  t
  88. 88 void Enter_LowPowerMode(void)$ z5 {% k; H* d. y
  89. 89 {
    1 m- q: o. {4 G2 O/ [7 L, \" Z% |
  90. 90   /* Set the device state to suspend */
    . v5 S. j  s% G1 |, O
  91. 91   bDeviceState = SUSPENDED;
    2 k" t9 z3 N, B8 c; V% m
  92. 92 }$ m; W8 \& `2 Z( i9 U0 w4 f
  93. 93 ( @1 ^( [# }0 @* S0 m
  94. 94 /*******************************************************************************
    . k) c; x* a3 W( E. Z5 d
  95. 95 * Function Name  : Leave_LowPowerMode
    9 S5 y$ ^# z& x/ W
  96. 96 * Description    : Restores system clocks and power while exiting suspend mode
    8 T) Z, s2 ?! |, O4 v4 V4 N* c
  97. 97 * Input          : None.
    + c4 t9 w9 ~1 e0 W$ R9 ^+ J
  98. 98 * Return         : None.  y3 g9 f1 C7 e; g$ n* A
  99. 99 *******************************************************************************/
    " u  a) \0 V3 i" @1 D/ z- u0 [
  100. 100 void Leave_LowPowerMode(void)
    4 Z" p! ?3 y4 ]8 h( U) \
  101. 101 {
    8 Z# Z: w& O" q& X- Z
  102. 102   DEVICE_INFO *pInfo = &Device_Info;
    2 J( I5 M- m+ a) }% l( I* V
  103. 103 ' }1 v4 E6 l' o
  104. 104   /* Set the device state to the correct state */
    $ E" y( w2 w; u/ ~
  105. 105   if (pInfo->Current_Configuration != 0)0 N3 X) S1 E+ x( M3 e
  106. 106   {
      i: |' u1 n$ m' s) ~1 S
  107. 107     /* Device configured */
    " T5 A, _* p2 {* M  ^  R
  108. 108     bDeviceState = CONFIGURED;
    3 {6 m. x, s# o
  109. 109   }6 r2 [7 J" {* o+ c3 W
  110. 110   else
    6 Q: m* A& R" b0 m
  111. 111   {/ u: _4 M/ Y% [; n) a! M: y( M
  112. 112     bDeviceState = ATTACHED;
    + s+ U1 s: F* _  U& o- y5 w/ ^2 \; B4 ^
  113. 113   }
    / o  I8 @" q5 c" }4 ]$ F
  114. 114   /*Enable SystemCoreClock*/
    9 f- S0 x5 E1 p5 H6 i# \- z
  115. 115 //  SystemInit();
    0 p4 j* k9 o4 x* y
  116. 116 }7 B, ^( W9 m! \. R
  117. 117
    5 x" a2 f3 y2 z6 Z6 [
  118. 118 /*******************************************************************************! ^; N% g* ?7 ]/ O8 `! W
  119. 119 * Function Name  : USB_Interrupts_Config9 d6 Z, P  ?6 K( [
  120. 120 * Description    : Configures the USB interrupts* v6 q. F9 y8 l" g: \/ C
  121. 121 * Input          : None.& Y' h; ~# H' H- E+ b/ `# R) \
  122. 122 * Return         : None.
    6 B- M# x, d$ [- |2 i
  123. 123 *******************************************************************************/! L+ S5 g+ {* r  D  o( |$ m. x) h
  124. 124 void USB_Interrupts_Config(void)
    5 `0 T- U9 ~  o3 N# v: Y; q3 m
  125. 125 {
    4 K8 X- R- O6 d$ V
  126. 126   NVIC_InitTypeDef NVIC_InitStructure;
    " E+ O+ f2 i$ S' o
  127. 127 # W( c4 j% O' O
  128. 128   NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;0 y9 W/ P' a2 ^: ~2 H4 n4 y$ b
  129. 129   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;# q- \  Y8 m- Y! n) _
  130. 130   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;, `% N+ {9 r& m# O/ |
  131. 131   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;2 w4 z( \" _# T/ s; w2 S& r$ Y$ t1 Y
  132. 132   NVIC_Init(&NVIC_InitStructure);
    $ }$ R- j6 @0 i+ L5 }7 \
  133. 133   # s/ W* w: y, s5 f
  134. 134     /* Enable the USB Wake-up interrupt */
    ! e0 ?: R  @& m* r; a1 R) h: Q
  135. 135   NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
    : p/ j, m  i9 L1 V: S# m: [
  136. 136   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;' k- m/ [- H3 R( T* a* O
  137. 137   NVIC_Init(&NVIC_InitStructure);
    7 n( z8 @* v- Y/ z
  138. 138 }
    8 ^7 S& W+ F. [& T! A  u& t* G6 T
  139. 139 - s$ l. K' h* ^: F
  140. 140 /*******************************************************************************/ g! d( N+ c) u6 V: [
  141. 141 * Function Name  : USB_Cable_Config
    # m$ j6 s$ R, o; w0 {6 u9 f
  142. 142 * Description    : Software Connection/Disconnection of USB Cable
    0 x. }: x$ {9 ^) T0 Y  A
  143. 143 * Input          : None.
    3 a, T; A  L5 @  d5 w2 i2 W/ ]
  144. 144 * Return         : Status2 e& p. g( s, J; V6 b
  145. 145 *******************************************************************************/
    # ?+ [6 H2 O* g: \' t
  146. 146 void USB_Cable_Config (FunctionalState NewState)
    : G7 ]: B9 u5 `" g) C  Q) [
  147. 147 {
    + ?3 n$ }, `0 t8 {+ y
  148. 148   if (NewState == DISABLE)( f7 b7 X3 _) J$ M7 c3 c+ ^: R( b: a) N
  149. 149   {, e7 F$ U. h) e# ?5 X/ ^4 ~
  150. 150     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    + x" J5 t+ g, \" x
  151. 151   }" ?% y2 O$ c. F) ^
  152. 152   else* ~$ A; c# @" K+ Y. h) |
  153. 153   {4 K; ]. ]$ A* k
  154. 154     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    4 E) C* D) f% D& L. N
  155. 155   }
    8 k# e9 Z! Y  j- i( L) y
  156. 156 }
    # f$ h+ g2 x) R5 w: ?/ k0 _
  157. 157
    - O5 ~3 t8 j6 `7 t1 b- o
  158. 158 /*******************************************************************************: @7 h0 G9 Y5 f: j* D3 u
  159. 159 * Function Name : void USB_Config(void)
    # w- C) d- `. y! [8 a- `: ^
  160. 160 * Description   : USB系统初始化+ \9 |. W# S7 ^9 U* c; z/ v4 n
  161. 161 * Input         : ' C9 L1 G4 s0 |0 c
  162. 162 * Output        :
    " t* Z: `. X' _7 l
  163. 163 * Other         : & t0 |' H% T2 H( D( F
  164. 164 * Date          : 2014.11.28
    . @. {$ j/ C6 J3 E
  165. 165 *******************************************************************************/* U2 A" c' A( ^9 T; I" ?
  166. 166 void USB_Config(void)
    5 b9 X( Z. L/ j( b
  167. 167 {
    5 X5 u, c4 t3 I- g8 Q( U9 p
  168. 168     Set_System();" c3 ~+ L( }2 ^5 I7 g
  169. 169 7 J, i' i9 o; b& Q5 v3 e" s, I
  170. 170     Set_USBClock();$ J& L' r- E3 a$ p
  171. 171 / t! e8 W, v  O2 }
  172. 172     USB_Interrupts_Config();* h: M+ S/ g% y# F/ o# L
  173. 173
    & o9 |, I0 o' z+ j. M7 a
  174. 174     USB_Init();
    0 k- a8 t( I5 h+ U6 S( D* I
  175. 175 }/ [: g4 Z# L. u) p
  176. 176
    + d+ D- O8 F: P+ j
  177. 177 /*******************************************************************************
    , \4 V6 ^* `9 q; D4 e# k
  178. 178 * Function Name : uint32_t USB_RxRead(uint8_t *buffter, uint32_t buffterSize)
    6 k6 t. E; {1 k2 n& [' N+ o
  179. 179 * Description   : 从USB接收缓存中读数据+ C+ S' E* n1 t+ ~7 `  X* Q
  180. 180 * Input         :
    / k6 y3 R& i3 W( \
  181. 181 * Output        : : ~" U+ u) V2 r  z
  182. 182 * Other         :
    % [" @3 P! l. D2 R- h' B
  183. 183 * Date          : 2014.11.28
    ) t5 E9 U8 K+ b2 q4 \( J3 T# v
  184. 184 *******************************************************************************/& O. B$ N+ j1 K; t4 R/ }0 x
  185. 185 uint32_t USB_RxRead(uint8_t *buffter, uint32_t buffterSize)4 c7 n) K) q4 S+ z3 @
  186. 186 {  a$ q$ |4 ^* H3 i
  187. 187     return QUEUE_PacketOut(&m_QueueUsbComRx, buffter, buffterSize);; n$ W, d8 s$ b" k  W2 c' b
  188. 188 }% d; A4 I- `1 C: |
  189. 189 /*******************************************************************************
    8 C6 b0 O4 }% q" l- W! Z
  190. 190 * Function Name : uint32_t USB_RxWrite(uint8_t *buffter, uint32_t writeLen)
    ! c$ O( S: T0 K# u! {( o5 {+ f; G
  191. 191 * Description   : 写数据到USB接收缓存中
    & J  ?$ O- J3 k* _. N$ p8 U
  192. 192 * Input         :
    9 e# [3 Y, p8 t" [) H4 i
  193. 193 * Output        :
    ! ?* c# f( ~1 O2 ~: k% {
  194. 194 * Other         :
    ; H$ J- Z# }% U) g9 S
  195. 195 * Date          : 2014.11.280 r/ W3 G8 H2 M; r
  196. 196 *******************************************************************************/% }! \1 x$ I8 u
  197. 197 uint32_t USB_RxWrite(uint8_t *buffter, uint32_t writeLen)
    : O6 l  o7 W1 M
  198. 198 {$ T9 h: p0 v" f0 V6 @
  199. 199     return QUEUE_PacketIn(&m_QueueUsbComRx, buffter, writeLen);
    $ l5 H' k- F3 E# F  Q' j6 I; Q
  200. 200 }0 g* A' E0 R3 J# P/ y
  201. 201 /*******************************************************************************
    3 \3 g$ q# e4 l9 Y
  202. 202 * Function Name : uint32_t USB_TxRead(uint8_t *buffter, uint32_t buffterSize)1 J/ Y9 v! B% x- u
  203. 203 * Description   : 从USB发送缓存中读数据
    , L" o7 s1 c& @0 }% V: Z- g
  204. 204 * Input         :
    0 _* w4 L; C) y! U" h
  205. 205 * Output        : ' J: _1 L* D1 u0 W: \; w9 N6 W7 Q
  206. 206 * Other         : # n  S' v/ `$ z5 o1 `  Q. @* N
  207. 207 * Date          : 2014.11.280 {0 _3 k5 F9 n; V+ i/ |1 Z
  208. 208 *******************************************************************************/! }# J& ~2 k3 k* i- D' c
  209. 209 uint32_t USB_TxRead(uint8_t *buffter, uint32_t buffterSize)
    ) n& t: a8 c% F# X  c# y
  210. 210 {
    / @( r: r6 ~5 X. i3 j  T
  211. 211     return QUEUE_PacketOut(&m_QueueUsbComTx, buffter, buffterSize);;7 d2 u; y" c( R: s4 ~! Z
  212. 212 }
    . r2 w4 Y$ I9 f1 c$ Q
  213. 213 /*******************************************************************************
    & i& k. g- i/ g* J/ M5 A! }# \& Z7 m1 E
  214. 214 * Function Name : uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)
    & O" H6 [7 a4 m4 Z; i1 R% n
  215. 215 * Description   : 写数据到USB发送缓存中2 d- W+ E2 u3 H
  216. 216 * Input         :
    0 U8 F. X1 a0 j/ f: ]
  217. 217 * Output        :
    - P3 P' m7 _! c3 O6 A  q0 l8 j
  218. 218 * Other         :
    6 }! q7 l0 {! d. Y5 F4 [
  219. 219 * Date          : 2014.11.28) e) C3 F+ G: E
  220. 220 *******************************************************************************/
    3 F! Y, C: b8 I; m; k5 Y
  221. 221 uint32_t USB_TxWrite(uint8_t *buffter, uint32_t writeLen)
    - u" |, k6 O8 n) M# I
  222. 222 {
    ) b- L- ~( m8 i! f  u
  223. 223     return QUEUE_PacketIn(&m_QueueUsbComTx, buffter, writeLen);
    3 D- b2 o) k- \) v- O3 b+ I' d1 L
  224. 224 }0 @* n. }8 q" Z# h. J7 y6 {9 f" v
  225. 225
    * c* L0 X% X4 \" Q
  226. 226 / v1 Z+ Z. s* U
  227. 227 6 O' j8 ]& O0 E6 s0 O
  228. 228 /*******************************************************************************
    ! r5 F8 \: a8 @- p( |4 m
  229. 229 * Function Name  : Get_SerialNum.0 h, A: Y- x8 s/ A) K
  230. 230 * Description    : Create the serial number string descriptor.7 ]; l4 I/ x# C* N5 `" T: F; i
  231. 231 * Input          : None.5 b1 z2 a  F. l* s' k( z1 T
  232. 232 * Output         : None.7 _# @/ F% P& _6 {3 M' |+ l
  233. 233 * Return         : None.- a& E/ d/ i4 j2 T7 e
  234. 234 *******************************************************************************/
    1 T9 D5 @' ~$ \2 W3 W. ?  e3 L/ U
  235. 235 void Get_SerialNum(void)
    $ n1 w4 P+ ?$ q+ B9 I/ d5 d$ p
  236. 236 {+ z* Z0 K/ P+ t0 n/ m
  237. 237   uint32_t Device_Serial0, Device_Serial1, Device_Serial2;- ~( C- W5 ?3 z2 m+ h9 z
  238. 238
    ! e; u! T# x: B2 l$ W  @1 }0 Y& `
  239. 239   Device_Serial0 = *(uint32_t*)ID1;
    $ H4 `% K6 H8 B  h* J
  240. 240   Device_Serial1 = *(uint32_t*)ID2;
    8 I4 S8 n5 }2 t( s
  241. 241   Device_Serial2 = *(uint32_t*)ID3;  
    7 x% o- x3 L$ `" I
  242. 242 8 w! ]% P+ ]+ v- R* J
  243. 243   Device_Serial0 += Device_Serial2;8 `9 ]1 J* l9 P% {+ H- K$ @7 D
  244. 244 $ p9 `- @$ H5 k7 n8 Z
  245. 245   if (Device_Serial0 != 0)/ n2 G3 F! P  v- H$ K
  246. 246   {4 x3 c9 p- Y/ `: i+ w
  247. 247     IntToUnicode (Device_Serial0, &Virtual_Com_Port_StringSerial[2] , 8);
    8 L1 G! Q5 l- k$ [7 P
  248. 248     IntToUnicode (Device_Serial1, &Virtual_Com_Port_StringSerial[18], 4);& o% R' Z9 u8 _7 {6 |
  249. 249   }% X4 i# J9 x( C/ }- c
  250. 250 }
    ' L) F* j$ r$ {2 |$ C
  251. 251 % z' M5 J# O) C. L- Y. y% x  ~
  252. 252 /*******************************************************************************) W' G/ I& M- k8 H% G5 s
  253. 253 * Function Name  : HexToChar.3 L* c+ b0 I2 g; g2 m; `
  254. 254 * Description    : Convert Hex 32Bits value into char.
    / i% M' E4 j6 Z. C
  255. 255 * Input          : None.4 s) f+ |6 W6 ]/ \, t  x5 d
  256. 256 * Output         : None., n0 @& Z' U! K. ]
  257. 257 * Return         : None.( l9 R& ?- m- g4 P  ^
  258. 258 *******************************************************************************/
    0 d1 E7 ~0 g0 h7 G* N$ L
  259. 259 static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)
    5 P4 I' V# K) j  }  ~) T+ m# h( Y
  260. 260 {
      F9 `: r6 h: r4 d8 ^1 e  f9 d
  261. 261   uint8_t idx = 0;9 W4 T2 ]) y# `7 q7 s
  262. 262   . m/ D" [9 L+ G2 m. b
  263. 263   for( idx = 0 ; idx < len ; idx ++)
    ' _2 m! g8 `$ x5 F: t- Z7 u
  264. 264   {2 @0 B$ \# S4 j. {
  265. 265     if( ((value >> 28)) < 0xA )
    - Y0 G% i" D  O. ^
  266. 266     {# W" T( `+ B5 E0 c6 e7 g( h
  267. 267       pbuf[ 2* idx] = (value >> 28) + '0';
    : W8 d+ b. q+ W" N5 l/ u& N
  268. 268     }
    0 s5 t. U( V4 E  |
  269. 269     else
    2 L9 g* ?( G4 U! L, p1 G' J* U4 h
  270. 270     {4 k: m7 }6 S$ ]. r
  271. 271       pbuf[2* idx] = (value >> 28) + 'A' - 10; 3 r, S5 B+ b2 o  v9 i* B
  272. 272     }
    : G! n8 A3 x$ W: x" r& E# N
  273. 273     * f% w2 L& k# T" l, u& S
  274. 274     value = value << 4;
    5 S) d, Y/ F- G- H6 N5 W
  275. 275     ! L2 [! G1 }" A$ M' o
  276. 276     pbuf[ 2* idx + 1] = 0;8 D+ \2 [9 G& S) \3 e7 e
  277. 277   }
    : u( t$ R9 p9 y+ q
  278. 278 }! D9 T5 Y+ Q8 ~% u6 l
  279. 279
    9 ^" h% d  B* C& B) B% H" s( W. j
  280. 280 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码

- S; k2 J% |: Y. I' K1 t6 L3 p1 E' h6 Y8 F5 \
这里要讲一下为什么要屏蔽SystemInit(),因为demo只运行虚拟串口功能,在USB未插入的情况下,是进入低功耗状态,插入时从低功耗状态退出后会调用此函数。当然我们在项目中一般不会这样,系统是否运行和插USB接口没有联系。所以我在下文中把进入低功耗代码屏蔽了,自然也就不用唤醒代码了。
图7
0 B4 r8 [/ D. w
300038465597900.jpg
9 w) l" c* H+ ], f, ]
关于USB口使能控制引脚,需要根据开发板的引脚定义来修改宏定义platform_config.h文件中,笔者使用的是神舟3号开发板,控制信号刚好和demo相反,所以修改hw_config.c代码如下:
代码3
  1. 1 /*******************************************************************************' w2 q: @/ F! o. ^
  2. 2 * Function Name  : USB_Cable_Config
    * \' a* D/ v0 Y( z; `
  3. 3 * Description    : Software Connection/Disconnection of USB Cable
    ! W9 y1 H" t: z$ V
  4. 4 * Input          : None.
    ' q7 G2 k4 t0 Q7 b# u0 c
  5. 5 * Return         : Status, r% v/ V8 z, {  V0 u
  6. 6 *******************************************************************************/
    : i' P( j7 y& L: Q' U" g
  7. 7 void USB_Cable_Config (FunctionalState NewState)6 ^7 z0 O4 ^4 h5 H* x* X
  8. 8 {  ?& @4 U  u( ~9 {5 F* }/ a3 x
  9. 9   if (NewState == DISABLE)
    - J" H" D, z3 b
  10. 10   {
    " T) C1 z/ y/ M5 H: s# A  ~4 \
  11. 11     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    ! m' L" `4 y( A* e, Q  m
  12. 12   }
    3 t. I  G+ i! k3 O8 V' l/ R0 S
  13. 13   else
    ! @5 [2 K/ |, |+ Q. a
  14. 14   {
      M. I1 u9 j7 l
  15. 15     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
    5 F/ q$ L5 k. }
  16. 16   }
    3 t& M4 r* w; K2 Y" F1 a% a9 L
  17. 17 }
复制代码
, z- m3 D+ U, n7 v% v* N
3,现在修改USB 回调函数中的代码usb_endp.c文件。使用下文代码替换:
代码4
  1.   1 /* Includes ------------------------------------------------------------------*/9 J6 h- P7 n! H" i
  2.   2 #include "usb_lib.h"
    : j! q6 u" n$ u7 O: G$ _
  3.   3 #include "usb_desc.h"
    ) [& r+ Y2 t, Q2 l9 G
  4.   4 #include "usb_mem.h") b& Q8 k$ r) w6 q7 @; F% S
  5.   5 #include "hw_config.h". b9 |- _; t, d9 y# o: ?
  6.   6 #include "usb_istr.h"8 E* ?/ q; W+ F, @8 p7 J
  7.   7 #include "usb_pwr.h"
    # H. X2 R6 b" J8 V: ]' A9 D7 L
  8.   8 % a, E: t* @: l
  9.   9 /* Private typedef -----------------------------------------------------------*/: n5 `$ q" u6 b
  10. 10 /* Private define ------------------------------------------------------------*/% B: g1 }: p* k- q
  11. 11
    : R6 w1 C; L$ L" x% T
  12. 12 /* Interval between sending IN packets in frame number (1 frame = 1ms) */9 a! T5 T; i/ J1 k: q8 v) X
  13. 13 #define VCOMPORT_IN_FRAME_INTERVAL             5! ?! j/ \3 J  u7 f% O) u* a
  14. 14 # z: y1 O. L7 k
  15. 15 /* Private macro -------------------------------------------------------------*/
      s. H( w2 U0 N" z6 s
  16. 16 /* Private variables ---------------------------------------------------------*/
    9 W1 @3 o& k" C
  17. 17 static uint8_t txBuffter[VIRTUAL_COM_PORT_DATA_SIZE] = {0};- r+ d# i* T4 t9 }- c+ {; x
  18. 18 static volatile uint8_t txFlg = 0;- B/ p. Y( I% z) r; B
  19. 19 static volatile uint32_t FrameCount = 0;
    1 e) P. w6 J3 d1 K; ]
  20. 20 3 D6 B! Q; i# J7 e/ g5 g
  21. 21
    $ j! Y* m" K1 W. E) D& C" U
  22. 22 /* Private function prototypes -----------------------------------------------*/, Q+ L; i, c2 I% n
  23. 23 /* Private functions ---------------------------------------------------------*/4 ]6 p" Z$ ^0 S3 _3 d( Y) B# ^
  24. 24
      _! P4 s1 c' q+ x
  25. 25 /*******************************************************************************
    8 _$ d/ g  X& H2 r3 ~3 ~
  26. 26 * Function Name  : EP1_IN_Callback8 f+ B/ h8 x! @$ @( B% \
  27. 27 * Description    :
    # Q* A, D! x8 A1 E
  28. 28 * Input          : None.
    8 V4 o& Y/ u3 O4 s
  29. 29 * Output         : None.. F7 w( l5 ~. U. D4 |
  30. 30 * Return         : None.) Q& T2 W) }5 }  R7 W+ l: F0 t
  31. 31 *******************************************************************************/
    ' N, \1 f4 S3 X# _; ^- k; x. ]
  32. 32 void EP1_IN_Callback (void)
    ; d( _9 Z7 A9 t  w) m0 l
  33. 33 {
    1 a, s2 T1 {* V6 C: z3 e& N
  34. 34     uint16_t len = 0;
    5 B' z2 W7 `/ U2 k7 Z" c+ {
  35. 35     
      c6 ^! u+ V# {# E: P2 _
  36. 36     if (1 == txFlg)
    $ F$ `8 ?% O' ~2 `
  37. 37     {  \; {( B; d+ E
  38. 38         len = USB_TxRead(txBuffter, sizeof(txBuffter));/ L0 A- ?1 Y7 v8 S8 n, ~
  39. 39 / M& z0 Z; k$ g5 Q
  40. 40         if (len > 0)
    % z9 j# [- }$ a
  41. 41         {1 l' \* X" ]/ A6 L* j1 Y; }6 g
  42. 42             UserToPMABufferCopy(txBuffter, ENDP1_TXADDR, len);, _4 S: u. ~9 G9 ]7 o3 g/ y( n9 K
  43. 43             SetEPTxCount(ENDP1, len);
    : `- B8 [: j* `  Q9 A" [6 I
  44. 44             SetEPTxValid(ENDP1);
    ) P2 }' r$ w0 q" L, H0 f4 T7 E" d
  45. 45             FrameCount = 0;
    9 Y8 P# E. m! J& B: d# M6 \. b1 Y
  46. 46         }5 X! s+ ]) S% x& o3 x$ W
  47. 47         else
    3 p' x+ J* v5 s  I# v" t8 k
  48. 48         {% P$ h* [7 W" |  g
  49. 49             txFlg = 0;' r/ Y. {, a0 I- Y) {  Y
  50. 50         }
    / J* Y' C* n. n2 m
  51. 51     }+ m# P8 |" t# w
  52. 52 }1 `$ d/ T5 Y, _( ~2 p  S
  53. 53 2 T! r9 D9 e& Z
  54. 54 /*******************************************************************************
    # U3 F/ E5 @8 o# `
  55. 55 * Function Name  : EP3_OUT_Callback
    : G  b3 ?2 q8 |9 I7 S/ Z1 t
  56. 56 * Description    :( ]0 t1 J& r4 Z/ y
  57. 57 * Input          : None.7 i: O1 ]0 s2 o0 K
  58. 58 * Output         : None.$ A% V9 e  Q9 x% p
  59. 59 * Return         : None.
    . y6 t, U" Q! S
  60. 60 *******************************************************************************/
    2 x# j* x  s) w7 ~0 ]
  61. 61 void EP3_OUT_Callback(void)4 S7 \2 d& _- Z: u4 U# X
  62. 62 {7 a+ J: s& J) Z1 P3 D2 m
  63. 63   static uint8_t buffter[VIRTUAL_COM_PORT_DATA_SIZE] = {0};& b7 j7 K9 t: R5 |
  64. 64 4 G) o, s' ^) e( w( A; `0 @( h
  65. 65   uint16_t USB_Rx_Cnt;
    , y& ]2 L/ z  X% p+ h! G% o2 {
  66. 66   0 ]! Z" K* P& K" b
  67. 67   /* Get the received data buffer and update the counter */
    : v1 k5 \: S+ l
  68. 68   USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, buffter);4 D/ Q' {) X& ~& p
  69. 69   
    + f1 k6 U/ H2 n3 J
  70. 70   /* USB data will be immediately processed, this allow next USB traffic being
    + R( v  R% d# ^4 ~& ^- `. c9 ?& H  w$ d
  71. 71   NAKed till the end of the USART Xfer */: J8 k0 Q0 b: c1 h- z$ }" W8 }
  72. 72   USB_RxWrite(buffter, USB_Rx_Cnt);5 F3 \/ H/ D! v' L9 t* C# ~
  73. 73
    6 G" }# \& K, m
  74. 74   /* Enable the receive of data on EP3 */
    5 _7 A+ l8 m+ P' a
  75. 75   SetEPRxValid(ENDP3);
    % ]% K' q4 c* f* b) t" `
  76. 76
    : {3 p8 b$ k& [5 g
  77. 77 }
    ) [; P  X  J0 m) e& k% A5 D; }' }
  78. 78
    / z, C3 m& }+ e' S
  79. 79   }% d% A- l* n
  80. 80 /*******************************************************************************$ f3 M6 Z1 R0 r  |0 S
  81. 81 * Function Name  : SOF_Callback / INTR_SOFINTR_Callback
    . y6 }, \# V1 b, t' d8 ~! u
  82. 82 * Description    :
    * k% W* l/ {+ I. Z
  83. 83 * Input          : None.8 c4 Y# W# `2 a' D: g# `+ ]
  84. 84 * Output         : None.
    , K3 s  q& A" w" l; U5 x
  85. 85 * Return         : None.
    ' h4 c; t( |* |4 ^+ f
  86. 86 *******************************************************************************/
    ; [9 q6 f7 B6 s  i
  87. 87 void SOF_Callback(void)+ `: G' Q9 }+ [# A1 ?2 z$ x
  88. 88 {6 s  [3 j3 o: g
  89. 89     uint16_t len = 0;
    9 |$ c7 h; |( u. V
  90. 90 ! h2 J- V2 U/ V: a- y: W7 c$ [
  91. 91     if(bDeviceState == CONFIGURED)2 Y$ ]) I& V* Z1 J1 ~, [0 Y
  92. 92     {
    % X6 }( h3 n! d& O$ L# e
  93. 93         if (0 == txFlg), k/ ^2 Q! P# V5 Q
  94. 94         {
    9 T/ Q; V; [: C( B6 C
  95. 95             if (FrameCount++ == VCOMPORT_IN_FRAME_INTERVAL)) `( A  u6 t* X( G1 T! O2 c
  96. 96             {
    6 B2 x% L& n5 r7 c& N6 _
  97. 97                 /* Reset the frame counter */
    / W) h$ @2 C3 |# l0 J
  98. 98                 FrameCount = 0;7 M& I! e2 S. h( p
  99. 99
    - B8 e" @: @, v. [3 B$ U& K6 n
  100. 100                 /* Check the data to be sent through IN pipe */% }0 N* V! w  o" A. G) g" _
  101. 101                 len = USB_TxRead(txBuffter, sizeof(txBuffter));
    $ k  K) r5 h( [, e  g4 D1 A0 k* T
  102. 102 ) N. f# W2 Q; \* n2 I" g, |1 G, z. R$ _
  103. 103                 if (len > 0)
    , r, n1 ]& w1 {
  104. 104                 {( \2 ~: ?6 _: B: B
  105. 105                     UserToPMABufferCopy(txBuffter, ENDP1_TXADDR, len);# Z. i6 L9 q. n
  106. 106                     SetEPTxCount(ENDP1, len);
    * M8 v, z3 m9 _1 P: |& [& I
  107. 107                     SetEPTxValid(ENDP1);
    1 a& p! g  L4 l' a* v/ O
  108. 108
    % i' W# |' l8 \8 Q9 g' R, P
  109. 109                     txFlg = 1;
    4 z/ F0 P6 q/ W) ~
  110. 110                 }
    3 ~3 u2 f1 _# {! ~* [7 w) l
  111. 111             }2 Q6 i6 X7 V' \! s% B+ }
  112. 112         }
    6 l# G" }( l, H& y8 F! g; R
  113. 113     }  # G+ n" x! M& d: W
  114. 114 }6 l0 n  U. k# g
  115. 115 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码
) m# U, F7 Q- h% A3 L1 F
: a+ M' S$ R( d' b+ _, s3 A4 K9 c
这里讲下大概意思,函数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也一起存放在上文章开始的链接中。

+ B0 l7 v( y1 M
收藏 评论0 发布时间:2022-1-13 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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