主要内容:
) ~- }& n C7 a" g4 \5 t1)STM32L4 IO 口简介;
3 e0 u2 M$ T9 I/ w5 F, X/ g2)硬件设计;5 Q0 ~/ B1 V, j7 @
3)实验准备;" i0 T. N; ^9 `
4)STM32CubeMX 配置 IO 口输入;
: ` G; ?, u% w T5)部分代码解读。/ W* ^6 v9 _- Z7 v8 ^- @* O
& r* a |$ E7 c4 H0 K U
一、STM32L4 IO 简介5 {9 W3 Q0 c2 R8 x' C }- |
在讲解跑马灯实验案例之前,先通过跑马灯例程学习一下一个工程文件的分类(个人觉得原子哥写的工程文件分类清晰,方便整理),如下图所示:) K. |; Q, q" Z0 n9 l; N7 a
1 i- u" z; W/ t4 S
8 _8 d4 F5 V" r0 N# N" }简单说明下工程目录下面的组以及重要文件:6 [, M3 x2 d8 k
1)①组USER下面主要存放用户代码。system_stm32l4xx.c文件用户不用修改,stm32l4xx_it.c 里面存放的是中断服务函数,main.c函数主要存放主函数;( i C& Z% l0 Q7 N; ^
2)②组CORE下面主要存放固件库必须的核心头文件和启动文件。这些文件用户不用修改,可以根据芯片型号选择对应的启动文件;
2 J/ F" w0 d! _$ z3)③组SYSTEM是原子哥提供的共用代码,比较好用;
1 R W$ V0 b. B4)④组HALLIB下面主要存放ST官方提供的HAL库文件;
- B- m6 D- ^6 l3 b! p5)⑤组HARDWARE下面主要存放每个实验的外设驱动代码,通过调用HALLIB下面的HAL库文件函数实现,如led.c中函数调用stm32l4xx_hal_gpio.c内定义的函数对led进行初始化。3 J) V, A# h. N" T* k% _
* t4 \8 A# ]3 B( ^+ s) P+ B5 N同STM32F1一样,STM32L4的IO由软件配置成如下8种模式中的任何一种(可关注其他文章,有更详细的讲解):
) Q! k+ a+ |" T1 Z, u1、输入浮空# d& L9 r1 F7 R/ k6 B j5 ~
2、输入上拉/ q0 m8 s1 K: V4 u
3、输入下拉
! W& j9 f# E4 O4、模拟输入% F" k+ m) \. V- b3 A2 U( B- J& W$ G
5、开漏输出# ^- c) ^& g& G
6、推挽输出# ^6 L' R% z4 E, K0 C2 o
7、推挽式复用功能
4 ~* n% L* u' ~8、开漏式复用功能2 F( J' }/ s8 L
# D3 n8 H( U8 R
操作IO口的简单步骤为:/ K# d9 J7 F* a. N
1) 使能 IO 口时钟,调用函数__HAL_RCC_GPIOX_CLK_ENABLE(其中 X=A~K);
4 {; b E0 _+ e2) 初始化IO参数,调用函数 HAL_GPIO_Init();
t* c5 N6 S* ?' {$ |/ a3) 操作IO输入输出。8 q% |+ ]& V4 j: q! _7 @6 V
' }9 u* U' g9 g实验功能简介:
/ Z& Y0 c5 P/ g; R5 i开机上电后,先初始化与RGB灯连接的IO口,然后每500ms改变一下RGB灯的颜色,实现类似跑马灯的效果。9 K9 a1 P. [8 c: X; c
1 q o6 P: a2 ?& Z5 Y
二、硬件设计
9 d0 n# g6 _. ~2 W) e! y: h2 v本章用到的硬件只有RGB灯。LED_R接PE7,LED_G接PE8,LED_B接PE9,连接原理图如下图所示:9 O: |2 Y. M Y% U5 Z
# e; c6 w* p( ?
" @& k* ?6 ^3 R( }# f: y) [; Z/ q3 Y
三、实验准备
* g3 n) o1 J1 O a/ W1)使用Micro USB线将PC的USB口与潘多拉开发板的ST LINK USB口连接起来;
' [0 R% l6 q" v$ Y2)打开实验1跑马灯(RGB)实验例程,编译通过后将程序下载到MCU;
4 s: P$ p5 x: G7 W$ X3)实验结果验证。
( p3 T* n: C5 |! T# i% L, j' P5 \7 r. @5 u8 o0 p# h! d4 O
四、STM32CubeMX 配置 IO 口输出
! ^2 A- \; i2 ?% n8 G关于STM32CubeMX工具的入门使用之前有讲过,这里不再重复。本节主要介绍怎么配置GPIO口的相关参数。: c7 R" Z6 l4 G$ s
打开 STM32CubeMX 工具
" o; ?4 G2 M! L0 X2 ]GPIO口的配置步骤如下:3 {! T- Z; ?) l
第一步,在引脚图中选择要配置的IO口,以PE7为例,在弹出的下拉菜单中选择要配置的IO口模式,如下图所示:
( u/ L: g5 S! U9 w$ d( T; G- ]5 C0 @- i6 }
. z; _4 ^4 E2 w5 ^) q
* j: T& A6 Q7 a: d" l7 s0 f上图的下拉菜单中,除了配置IO口为输入输出之外,还可以选择IO口的复用功能或者作为外部中断引脚功能,比如要选择IO口复用为SAI1功能,那么选择SAI1_SD_B即可。对于跑马灯实验,PE7作为输出,所以选择GPIO_Output。
3 \/ `- l/ H D6 e6 b+ Z
7 t. y% u$ l) i' Z: [% M第二步,进入Configuration->GPIO,在弹出的界面配置IO口的详细参数,如下图所示:
- |5 a' G" u0 @# \# Q0 M- {. s" p2 R }- f; \2 t# L
7 Z1 W. ?+ p9 a
) |1 {7 }9 h$ i1 o5 [5 U3 t m/ V+ E
; h& A( S7 U1 l8 U5 C5 v9 M
9 V4 i* F3 U% S8 J# g. I在IO口详细参数配置界面,点击要配置的IO口,会在窗口下方显示该 IO 口配置的详细参数表,这些配置项的含义具体为:2 K& J4 {; O* B f+ p
1)GPIO output level:默认输出电平,可设为Low和High,即低电平或高电平,本实验默认关闭LED_R、LED_G和LED_B,择设为 High;0 E# m5 o. t5 L# t7 c* k
2)GPIO mode:用来设置输出模式为:Output Push Pull(推挽输出)或Output Open Drain(开漏输出),本实验均设置为推挽输出;
. O; V. |& M$ Y0 Y2 x+ a4 F0 g" ?3)选项GPIO Pull-up/Pull-down用来设置IO口是上拉/下拉/没有上下拉。本实验设置为上拉(Pull-up);* G# D: Z- Z- B' p3 d9 F' I
4)选项Maxinum ouput speed用来设置输出速度为超高速(Very High)/高速(High)/中速(Medium)/低速(Low),本实验设置为高速 High;7 f# H3 e8 \% y& t' s
5)选项User Label是用来设置初始化的IO口Pin值为我们自定义的宏,一般可以不用设置。# b% s' d% T* q9 B3 b* A
PE8 和 PE9 的配置方法和参数都一样,就不重复讲解。
8 X! d7 z5 j5 w. K, d$ T( Z' T% ^- C5 { K
GPIO配置完成后。* N7 [3 x$ O1 `
0 F5 Z; m( o! Q, O% `# N& d
打开工程的main.c文件,该文件内部由STM32CubeMX生成函数MX_GPIO_Init,内容如下:- static void MX_GPIO_Init(void)
, K. H$ k, Q) \( k7 i - {
- `" r' s) v7 E8 M - GPIO_InitTypeDef GPIO_InitStruct;
& ]/ Z/ Q0 C" g/ K3 c2 `# l - /* GPIO Ports Clock Enable */ 2 P( u8 \; `. Y' P3 }1 o
- __HAL_RCC_GPIOH_CLK_ENABLE();
$ t L5 @/ C( {" h - __HAL_RCC_GPIOE_CLK_ENABLE(); 1 T9 W7 D1 b6 e) F
- /*Configure GPIO pin Output Level */
. f! k! C- t) O. ]) p, ]; I - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_SET); ; s/ R3 G9 ^. R- H$ @
- /*Configure GPIO pins : PE7 PE8 PE9 */
( Q. {! }4 u" X; B - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
4 n9 w. N( O' a. G2 p- i, G - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; $ y0 Y* u' S% d' b& ]1 p$ R( R* \1 u
- GPIO_InitStruct.Pull = GPIO_PULLUP;
3 _$ \; W9 y+ r$ ]: I$ g - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
0 s# z9 {9 L, a4 {/ `7 f$ S - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
6 @/ k0 m% b* j4 M% R2 M, ^0 }9 z - }
复制代码
# Y# Y9 L( v3 v/ d6 Z8 K( y五、部分函数解读8 ?/ _9 E4 ?# k
对案例库进行适当修改后(主要将两个子函数分离出来,这样代码显得清晰),部分代码如下:% d# K) T4 C2 E
1)main.c函数
" N2 F% g- s: i& r6 X( e; K
; \9 a6 i$ S* P$ \- /**7 V4 \) _+ ]5 C, w& @: m. X
- ******************************** STM32L4x *********************************9 S0 ?" y6 M" y. Q9 W
- * @文件名称: main.c
7 r$ T$ b% B( o) V - * @修改作者: 闲人Ne
" u, ~- K9 }- F3 N2 O6 S: Z - * @库版本号: V3.5.0
0 [8 K& f6 j5 ], S$ h; j- h Y - * @工程版本: V1.0.0
0 _9 P4 \/ V' @1 ]8 f$ l - * @开发日期: 2020年12月07日
5 q2 R5 A$ S& i! G9 j! O* F - * @摘要简述: 主函数
; Y. S/ ?8 z$ l* a! D8 ^1 s- D - ******************************************************************************/7 r! ^0 w, Z6 T4 }7 K) ?: W) c
- /*----------------------------------------------------------------------------7 L1 P7 o: {: i& Z* o4 f
- * @更新日志:& x* w! J1 v/ {( s! t
- * @无$ _6 |$ @5 w, B2 b/ R+ H
- * ---------------------------------------------------------------------------*/
: h1 f+ p7 k) G8 m( L: k; f - /* Includes ------------------------------------------------------------------*/: y( g7 d9 Z0 \ `9 J7 |/ {
- #include "stm32l4xx_hal.h"
% J7 L* } h: v1 c8 k7 y - #include "led.h" // 初始化LED灯的引脚配置
0 S' Y' m; j& g - #include "sys.h" // 初始化时钟用3 m/ m0 i( E/ W% [5 V' A
- #include "delay.h"
/ r0 h! ]. k7 o. h/ t - /************************************************
1 q5 B6 y$ p8 G - 函数名称:int main()
2 n1 z+ [' M; @ - 函数功能:主函数7 i+ a. A _' v( E0 P
- 入口参数:无
3 U1 A$ z/ V- h( x F* M& q2 [. b% i( q - 返回参数:无
k: S" N' I' f$ v3 v' i8 P& A - *************************************************/
, M$ x" _' p% T - int main(void)1 ^, [5 `+ h5 [# [( z
- {
) D: `& S+ b' [/ s - u8 color=0;2 K/ t7 I2 t) `7 i
- HAL_Init();& `' l% n, h& [. ^+ O# t& d5 W
- SystemClock_Config();* v3 W3 W3 e% A k( e7 `
- MX_LED_Init();
+ ]3 s! D) c0 K: c3 j; H6 ^ - delay_init(80); // 初始化延时函数,80M系统时钟" \2 S) l2 _9 W0 {4 G, p! s! {
- while (1)
# [. c9 `9 G$ ?* z7 K6 X( a - {; t. D& j) A5 T z
- switch(color%8) // 取余数
! G% X' R9 M C5 B I! [ - {
7 p2 M, i5 ~ u: }" Z6 b# E ? - case 0: // 余数为0时
" D; F1 Q7 B1 C! Y0 f - LED_R(0);" x( b4 y# K7 U6 @
- LED_G(0);4 Q& ]$ y& V, X9 y0 O
- LED_B(0);
& b6 p9 E Y) |5 r) t5 q - break;/ t: B4 m* y' X& O& i3 v
- case 1: // 余数为1时
* R7 i+ y9 G5 J, h7 U - LED_R(0);8 r, c( U! J7 |3 P$ @9 @# \2 s
- LED_G(0);8 {/ v i; A& l) N( x9 k
- LED_B(1);
Z% o% J( w8 S0 @$ ~4 B1 v6 I4 ~. K0 o - break;
" i" ]0 e$ l+ |% X6 e! Z' C& {. _ - case 2: // 余数为2时
7 f) O" s4 r3 C( _$ m' ]6 } - LED_R(0);7 i; u% y7 J# s. \) P" ?
- LED_G(1);
6 F* {, N7 g& D2 S - LED_B(0);0 z' J8 n. U, V1 n. y
- break;1 ~4 @0 l2 B9 z! z$ k" u
- case 3: // 余数为3时2 @, i4 t! E6 T. ]# f' O
- LED_R(0);
7 @. _( J9 r8 q - LED_G(1);4 ~% x$ w1 r! H' h/ B! b
- LED_B(1);
+ ]- Y) ?. f0 [7 N - break;
& a- A* t0 Q2 V6 P' g' u8 t/ f- [/ R - case 4: // 余数为4时6 W" u! i3 y9 z9 ^8 o4 M2 ]
- LED_R(1);' j2 g% ~! O9 _$ e( {
- LED_G(0);2 H, ?: u2 u ~ K9 B: h
- LED_B(0);& \8 n r. D% d9 I* H
- break;
! h' V# q! a, J+ o2 s1 O3 ?8 F - case 5: // 余数为5时
! e0 P8 Q H" T4 c3 \9 ^ - LED_R(1);
6 i2 t4 M" J: r, \1 ] - LED_G(0);
4 L8 e0 Y& I* X( z - LED_B(1);4 D/ i2 M( d9 Y n$ v! U) y: s; p7 \
- break;
' O& S3 D& H9 x( ` - case 6: // 余数为6时1 ~! l4 q1 S% U5 {
- LED_R(1);
5 `) d) |2 c; S8 N: w - LED_G(1);
! @. V# t; O% L - LED_B(0);
9 e+ H* g+ X: j8 Z6 L4 C - break;* |- ]! b9 a: W3 C
- case 7: // 余数为7时
+ C+ [6 f. h& u6 t2 ` g - LED_R(1);
n& Y0 r/ g; N4 O" F) p, T - LED_G(1);$ t4 o( f9 T5 V9 Y2 i8 ?: {/ P
- LED_B(1);
3 Q4 P" W! O2 d - break;
8 t+ ?* B- G1 p9 `- U - default:
6 `$ N/ A" x V+ Z# H: ]- a - break;
0 N9 M5 T* ~0 Z8 `( o* o - }& ?$ w; w1 H* J
- color++;0 A9 r4 M$ i, B A; A
- delay_ms(500); // 延时500ms就改变一次颜色
5 |: {3 g0 e8 [$ M8 S - }
0 e1 T0 }5 {' P8 y6 {( h: H - }8 Y7 _) U- K( d: k4 g# i: A
- /****** Copyright (C)2020 闲人Ne. All Rights Reserved ****** END OF FILE *******/
* G' F! ?* l7 O$ p7 M) `) N
复制代码 ) j# K! z8 i1 X# a5 }' F
2)led.h头文件
[8 R4 u; \ C- V! F& b* h: ^' }/ `- q6 t2 h& |3 X. a% Y7 c
- /**
! n& Z3 d* D, K0 M6 l - ******************************** STM32L4x *********************************; j- ]+ [7 Y" n9 |8 @
- * @文件名称: led.h/ q% Q/ @, `* Z" |9 H2 U
- * @修改作者: 闲人Ne" x1 V+ Y) Y2 o X) \
- * @库版本号: V3.5.0* @0 k3 c3 k, u% R) d; R
- * @工程版本: V1.0.0
) [; Z. D0 U! o. U; Q, X n, @! \ - * @开发日期: 2020年12月07日
7 J3 D( [5 w# r2 Y) S( S5 G+ Y - * @摘要简述: led.h头文件
|1 J- F( R5 h, A$ y" a9 m+ Y0 l - ******************************************************************************/
) y1 ?/ }2 q" k% T6 P - /*----------------------------------------------------------------------------
/ ]. b) g' |1 c* q" a# k - * @更新日志: U9 R( v3 Q) H3 [2 d0 |( L
- * @无3 b4 w% n( {( a; j/ B3 q
- * ---------------------------------------------------------------------------*/" B- l& R# g$ Z4 f: G
- #ifndef __LED_H
, ?( M" r* P& r9 ^& j5 X - #define __LED_H
9 a" A5 `! ~2 M9 ^ - /* RGB接口定义 ----------------------------------------------------------------*/
! W, F1 V* G3 B - #define LED_R(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,GPIO_PIN_RESET))
! y0 F* ]! M( P# v& t; X - #define LED_R_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_7) // LED_R电平翻转
$ b3 n/ p$ S- w% I - #define LED_G(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_RESET))7 B- J @1 a; u1 Y3 Y) K$ ?
- #define LED_G_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_8) // LED_G电平翻转
3 H5 h! P5 @% w% j$ s - #define LED_B(n) (n?HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_RESET))
7 X8 J' V& T$ L! y& v& K' e - #define LED_B_TogglePin HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_9) // LED_B电平翻转* t: l. [& M* p G2 J
- /* 函数申明 ------------------------------------------------------------------*/
, o. Z) i- p+ S - void MX_LED_Init(void);) B3 b6 P/ H0 @
- #endif /* __LED_H */
, C' i( `7 o/ g9 {: I - /****** Copyright (C)2020 闲人Ne. All Rights Reserved ****** END OF FILE *******/
复制代码 - x2 i d, X: F( f1 Q" Q+ d* q
3)led.c源文件) ]2 ^1 M# n0 C5 f0 F3 V0 J+ o
5 ^$ X3 a& V! D% \- e! G: Y6 l- /**3 B) @' ]5 j2 {- L* v
- ******************************** STM32L4x *********************************
* j( ~1 J0 }8 ?( I& z - * @文件名称: led.c
1 p, G7 ~3 B8 y6 V9 D; p" f - * @修改作者: 闲人Ne
4 |- [* D4 O! i3 G& U - * @库版本号: V3.5.07 k2 @% p) |- ]) v$ g9 k. g
- * @工程版本: V1.0.0: D( p9 Z5 ]9 M5 Z$ t. j
- * @开发日期: 2020年12月07日) F1 g" S7 `8 q* ]3 }
- * @摘要简述: led.c源文件% J1 r! h- P' F, c$ @$ k8 \* ~
- ******************************************************************************/
# u5 m0 x0 j S) m5 C( `2 v" u$ r - /*----------------------------------------------------------------------------
b+ N: e; `1 G' `$ d o - * @更新日志:
- r" p. Q4 [! { - * @无5 S3 l4 _0 I3 j& d. E' X8 e
- * ---------------------------------------------------------------------------*/. j9 w" z% E h) A5 _6 o
- /* Includes ------------------------------------------------------------------*/
. D5 x, e6 m7 k9 H: s5 v6 n$ V - #include "led.h"
* P. B- @9 S6 a - #include "stm32l4xx_hal.h"
2 f) P% G! h% `! u6 U- e - /************************************************
, q- S$ `+ A. @6 ~: |6 l+ N, } - 函数名称:MX_LED_Init()% G7 i u# V0 `; l: d7 l& K. C
- 函数功能:LED管脚配置: }* t8 {+ ]7 y) a) C: ^
- 入口参数:无
9 W. }. X( ]' X: V - 返回参数:无' n- N6 P1 [! r9 P- o: `
- *************************************************/
1 S8 V- K7 S' `5 ?5 x- F* g - void MX_LED_Init(void)
1 c$ D2 e7 ]) B - {1 a* Y9 R4 P5 M& v
- GPIO_InitTypeDef GPIO_InitStruct;
- ~% N1 Y3 [8 o - /* GPIO Ports Clock Enable */8 C; Z/ v) |$ M/ J3 j7 V# |# I9 X
- __HAL_RCC_GPIOH_CLK_ENABLE();% ?" n$ y2 n4 o
- __HAL_RCC_GPIOE_CLK_ENABLE();
. n4 h) b# [+ z4 \ - /*Configure GPIO pin Output Level */
9 e) B! L3 r. R; V5 t( Z - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9, GPIO_PIN_SET);2 H& `+ T% t7 g4 e2 E! g
- /*Configure GPIO pins : PE7 PE8 PE9 */
' `5 t! d& I# i& v - GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;) g2 d/ C' a7 c2 j
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;8 l5 v$ i* N+ G/ R6 B( E
- GPIO_InitStruct.Pull = GPIO_PULLUP;
; J; k, x2 A' m! C& { - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
9 ]9 I+ N7 y, ~# g6 K5 d& }. T* d. c - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
4 }" p) ~! V5 _ - }# p) y( S. k4 y- X
- /****** Copyright (C)2020 闲人Ne. All Rights Reserved ****** END OF FILE *******/
复制代码 5 R! P5 d! ~8 m/ ]
备注:在用STM32CubeMX生成代码的时候,main函数里的SystemClock_Config()子函数里少一行代码 RCC_OscInitStruct.PLL.PLLM = 1,导致前期在main函数里设延迟时间,总感觉与实际时间不符。补上这行代码后就好了。& \& \/ J: A+ V- U
————————————————! J3 Z0 P# f4 s& O+ `
版权声明:天亮继续睡
' d% ?% u1 Y/ V( S5 P9 y' {1 U# O1 b% U! T7 m
|