前言 p, s) h4 d% i
本次实验以 STM32F407VET6 芯片为MCU,使用 25MHz 外部时钟源。. I. L6 @% e' A4 B" f# J& w
USB通信引脚 与 MCU引脚 对应关系如下:
. M* _7 j, S. ~: x6 i) z( \+ \* l8 @' K& e1 m2 W2 O- J# `
$ j \6 J- G" E1 \: o
8 L: o! [1 B; N' H5 {原理图1 U" z5 @9 `8 k; ]+ N O) _. f
' d$ V( X9 r4 I6 g3 _* ^9 s3 ?
7 y5 l% j3 u Y" |& Z4 w) |7 D
1 m$ }9 K$ R2 v- y9 w- b( k
0 s; p2 _2 u* T0 G) j" r2 g
一、使用STM32CubeMX----新建USB实验工程: ~' z v% F" j. e! T* n& j
步骤1:打开 STM32CubeMX 软件% S" W9 U: J/ y9 q9 u
具体 STM32CubeMX 界面如下:; }8 L* U/ B8 w( \9 X
4 I9 R+ y0 g! d8 ?6 T5 v
. ?" @( b' D1 U( f! n( D
( l: k" E. X, }* N0 x3 V
步骤2:选择 从MCU开始我的项目
* h+ q! |. b" y# E a% i) s* g) S0 d: Y3 |1 C K" S
% i: v; L* S% W# D3 s3 n/ {. T3 G7 }# ]. N: c1 K: B
步骤3:选择MCU芯片5 v* q2 U& }6 |7 d' }
我们本次实验选择 STM32F407VET6 芯片做 MCU。
5 U' M( C! h# l+ V: g3 `( a; N( V" [ B" R1 G
1 p9 G$ D, }) W0 O1 Y, \
( P4 v% @: L3 R4 x6 R
- X& s; k0 E% G* Z2 F进入工程编辑,具体界面如下:5 k1 l; v& y3 P* q! a+ B2 x
# O% ^* W4 _1 s; H* t v3 N
0 O5 B3 b5 G" `" E6 }. |/ X' L* {9 ^
! b1 X5 s. x; g步骤4:设置烧写方式为 SWD模式
k, o2 w' q7 ~8 B& V8 }0 l这一步必须选择一种烧写方式,否则烧写一次程序后,芯片中就没法再次烧写程序了。需要硬件重启才可以重新烧写程序8 @& b+ K9 w+ h+ j2 {
: V' p1 g& L, |
/ F# j3 X+ w$ S, e
8 `0 i5 A- ?) b. j i: f
步骤5:设置时钟源
' _/ g- [* \1 a7 c* I5 v- h2 q设置外部晶振为芯片系统时钟源。
3 ]% h7 n1 s) S1 u
( O5 t. ]5 p/ z5 I
1 f. M, `' y4 q) r% r, P* k6 L) J5 _# R& Q
步骤6:USB通信配置
8 o; _/ d Y" o- l6 H激活 USB 设备
' |7 ^0 S8 p& E2 |
) J# c2 \9 I7 C3 t
8 e+ V+ z+ R0 N/ i- Z' x
5 O. o5 f2 [; g& p+ g选择CDC模拟串口, J* r4 |9 j% m: b6 @' ?
, e; [3 x" n) e# ?. h4 n+ N, M* W& g
/ q* O- _+ k! D4 Q. }- ~7 u
9 I }0 d) A7 }: z8 ?$ _: m, d* H# F5 I6 q' m' s0 a
步骤7:设置时钟; Q8 B6 o$ ]/ X A- o
因为USB的时钟需要 48MHz,所以时钟配置如下:
+ k' t- f7 N1 p9 |8 U! t m
& ]; A% ?6 W3 K, w( Q( n* G
" m% o4 w/ o9 o$ r' T; f/ I
: h: P0 t& X6 S1 t6 ]. [( l! ?5 l$ D
步骤8:项目编辑5 X% v* V* |8 w! k
堆设置大一点,否则识别不到USB。; U( n/ |1 N4 u K0 i/ {
7 h; Q" w: e5 {1 Z D" s$ B
- q4 S# [: [; j" k
2 H, H3 o! P8 x! F步骤9:代码生成编辑- c* P2 T+ B7 X/ }5 t) E- h: D
K0 ~& X1 P K5 L
2 R( c- l5 p3 D2 \- K
' @/ S8 H; k; n, E: }
步骤10:点击 GENERATE CODE 生成代码- h4 M3 }" l% v2 B V
7 Q/ I- p5 w8 ~9 V
; [6 j, K" }4 S& b" C3 z
% |" N8 _ ^9 X6 h" k9 F新建的工程,已经生成,接下来就是对工程代码的编辑。
& y1 y- ^( O$ W& s% n% o. @
6 M5 M. N* z, l* ~: u
4 \% h3 C# L* e# z二、使用keil5----编辑程序' Z2 R* r; I2 j) d1 B6 m: e3 Q
想要使用keil5打开工程,需要电脑先安装 keil5编译环境,具体操作流程。
) G% |, q7 O* Y! t. d+ @% s
2 k" a; @# v/ y步骤1:使用keil5打开工程
! g% f- Z- C% g) T. G点击工程文件中的MDK-ARM 文件; x' n9 N/ l' i5 z2 F# E% n% m1 F. H
/ B3 `# R9 y, U
& B1 T1 B- U& l% |# x5 l8 \9 c; L( B1 c, x. ]5 }
打开keil5工程3 W: t4 e. V5 O# N8 x( J4 J
, N' ?4 Z( m6 x8 A+ o, d T
+ X$ J4 d$ @. N$ h8 L. y' F F; g
步骤2:用户代码编辑位置- ?/ F7 ]! i; O
用户代码 要写在 USER xxxx BEGIN xxx 和 USER xxxx END xxx 之间。/ q1 V9 M. J0 C8 \
这样下次使用 STM32CubeMX 重新生成代码后,自己写的代码不会被删除。% t. W; s! Z# a
$ g) s7 L( F( j" @, t
: c6 W' f, S# D' p& j4 a& T' |5 p/ R9 b& B, m: M- w& l
步骤3:查看USB虚拟串口的端口9 B, J4 R' k `; c$ I: v G1 w
首先编译程序,然后烧录程序到开发板,具体步骤如下:8 ~# q. U: p- F( c5 ]
. g7 p9 s7 ]+ N# u( y烧写完程序后,连接开发板和PC端电脑,然后在设备管理器中查看USB虚拟串口的端口。
9 i4 [+ O0 D( Q, e" j' Z7 x3 i) X有以下端口,就说明USB虚拟串口功能实现了。/ L! T; k2 s+ X* I
1 b7 g6 n# r7 u* x! G9 o
- H2 w) m$ w+ T& H6 G
2 Q" m1 q3 D- m9 K6 ?, }! G步骤4:USB虚拟串口发送数据' H0 N6 {# c% c7 n2 b% q" m: w4 h& h3 Z
在 usbd_cdc_if.c 文件中有 USB虚拟串口发送函数:
) n7 ^, V5 j* q- /** USB虚拟串口发送函数, ]7 i( ]1 y% [1 ^
- * 参数1:Buf 要发送的数据缓存区- h+ @1 V; q, p1 h
- * 参数2:Len 要发送的数据个数
$ }5 c9 ?5 ?/ U3 l - * 返回值:USBD_OK-成功,USBD_BUSY-忙碌, USBD_FAIL-失败
# B: I, G, z. q: T - */
3 y" i6 E$ T, R9 b" Q - uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
: S8 r8 d) X: h( u4 o
复制代码
' W5 R: E9 X/ u4 G将头文件 #include "usbd_cdc_if.h" 添加到 main.c 中。
/ A p$ o0 B- ?( [7 ^0 `+ |
7 u. o5 H" D3 Q/ _+ \
$ U1 j% f6 k" d. g! z4 U& M! O
# Y$ |! l! i! T- V在 main主函数循环中添加 USB虚拟串口发送函数5 r: I! M" I% v: j J% w
- int main(void)
- V( ]8 F* W( s% @9 ~; B - {* V2 p' E& k9 r1 a7 `" s) }
- /* USER CODE BEGIN 1 */) ]' t7 J9 A% w/ {4 v: q! l: b& J* }; A
$ n* G7 Z9 z) m, K- /* USER CODE END 1 *// u; ^3 L7 q% a( H+ X; \# d! K
3 W) N7 ~0 X2 u8 K: U- /* MCU Configuration--------------------------------------------------------*/
5 A' C) E, ^$ r0 y1 b) h" P - $ W( w. `" ]6 ~
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
* h2 f0 ?8 w) E4 ? - HAL_Init();( t8 Z4 c( _7 h# C' A
- 8 J' C: V& @: F: m& J8 x
- /* USER CODE BEGIN Init */
- r( n( S* \/ Y0 V- [& A, t8 \: r8 i - " M9 `/ A2 a8 i5 u( _0 j5 m% T
- /* USER CODE END Init */
) a5 M% c& l2 U0 C/ ^7 M
5 t8 M0 q/ J6 r- /* Configure the system clock */
& |1 B/ H, `9 x9 G& r - SystemClock_Config();
: ^% M, F: E7 C
4 [3 l; l% f: d% Q: \- /* USER CODE BEGIN SysInit */7 F- b0 c3 S5 Y- b" E
5 K) s; `2 z. H2 o. F( w+ j* Q- /* USER CODE END SysInit */) ]: @0 o) }# O8 Y+ R9 C( u3 c5 k
* D t2 [; q U" s) E- /* Initialize all configured peripherals */7 Y" n8 U% f. P p6 h( _% a
- MX_GPIO_Init();
) Y7 d9 {# B& x& F - MX_USART1_UART_Init();, R* ]. H/ K3 D- e9 l' \$ g3 W
- MX_USB_DEVICE_Init();5 t1 L6 F: c0 N/ T; n
- /* USER CODE BEGIN 2 */* U4 a4 j0 U9 a8 l; G. Y# P
- 8 a/ _0 R- |! c3 o7 A, _
- /* USER CODE END 2 */8 ]3 l( X$ s- b
) Q& y9 I K* I- /* Infinite loop */! }. @6 N$ ?7 ~7 C' E8 l2 d' k
- /* USER CODE BEGIN WHILE */
% d" z a/ m* n* Q - while (1)
% u7 }+ c( j2 c& ?( L1 I - {
3 |. u' b) t& j T - /* USER CODE END WHILE */: G8 X& w1 ?3 X! I) _6 W
- 9 P, ?; w9 H/ e. @) f
- /* USER CODE BEGIN 3 */3 U1 x5 z$ Z' B% c$ j
- CDC_Transmit_FS("工欲善其事,必先利其器。",strlen("工欲善其事,必先利其器。"));
2 x7 ]8 m3 b9 N2 F; B6 z% i - HAL_Delay(500);
* I! S1 {! _' L" f6 G7 X - }
5 E8 b+ q1 ^8 ]0 s - /* USER CODE END 3 */' e# i7 T. w9 h1 j$ u i; g
- }
2 }+ j8 X/ d6 s1 F) Y6 k6 R
复制代码 7 ~; ^; S% P( _# i
使用串口助手打印数据如下:
9 M& m8 z( Z# P# H/ g' s
% I _1 {+ a/ X0 b ~' Q- z
3 ~$ C+ ~' [5 @1 v
. E. _ Q" |5 K步骤5:USB虚拟串口接收数据
* i5 E4 Z, I5 c/ a% q在 usbd_cdc_if.c 文件中,有 USB虚拟串口接收函数:8 d) P5 d0 W% k: X, U/ p; l
- /** USB虚拟串口接收函数
8 p9 L" w; q2 B- [ - * 参数1:Buf 要接收的数据缓存区2 m4 Y; x4 l6 w& [7 [# p
- * 参数2:Len 要接收的数据个数
! d: w) J) N9 h8 G9 a" z6 D" M1 B - * 返回值:USBD_OK-成功,USBD_FAIL-失败
3 C) ^0 i* {# C" ^- C - */3 \2 B' u! q+ w+ A* \, x
- static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len);
6 B" r2 c1 r/ ^
复制代码 " m& C4 U6 b$ d7 |) h7 P
在USB虚拟串口接收函数中添加 CDC_Transmit_FS(Buf,*Len);,将接收到的数据发送出去。& @5 d+ m8 e/ W; [' o
& Q& O0 D1 `. Z7 }
5 A. U, A9 n4 V9 V
$ |4 V! Y9 ?* ?: Q' n使用串口助手调试如下:: q( i) o( x( E! j4 a2 p, [+ U
1 W, y, X. d; C
; b* E! Z" e& i& N+ G/ }
+ n3 Z& y, O7 i2 A6 c' C————————————————
. c1 q" @" @' Q2 c( q; o版权声明:根号五
( ? H4 `' Z' v8 L/ l6 m! o+ t1 s: n5 e2 P! s
, g0 e5 O4 o$ p( M7 f0 u7 M+ R
|