之前的点亮小灯实验用到了GPIO的输出模式,但是对于输入模式没有用到,这次小R给小伙伴们介绍GPIO的其中一种输入模式——上拉输入。按键出现在很多的应用场景,按键处理更是一门学问。因此,小R给小伙伴们介绍GPIO的上拉输入模式并简单应用于按键实验中,通过判断按键的状态来控制LED灯的亮灭情况。
7 N2 m: \& k" p7 M3 z1 }
3 J, G. t' N- S- w6 o3 ~首先,需要了解的是:当IO做输入使用时,通过调用函数GPIO_ReadInputDataBit()来读取IO口的电平状态。其次,按键是需要消抖滴。最后,既然是按键实验,就会有按键电路。按键电路如下:' u4 O8 p# v; ?/ h
5 F8 K- L Q! q. M. x8 O; T
/ D: [$ }8 A1 o
: l/ R+ S/ p+ K- y" p& }
电路很简单,将按键接在I/O和GND两端,
, p* E0 b2 u% x3 c0 P' `& _+ e. i$ R' s! ^) Q( V. l ]# U
I/O配置时设置成内部的上拉输入,- o/ j% a1 R2 N, j) ?: q1 [4 v3 D
7 A5 {) F1 S% y& l4 O! B- c% h这样按下按键接通GND,输入低电平;7 H( L3 E8 w) E3 q
1 S1 O& f0 E. G1 _: I
也可以将按键接在I/O和VCC两端,- R2 i$ q0 m5 ~& a6 Y! D8 ?9 S
, s3 o! X! i4 {( e: |I/O配置时设置成内部的下拉输入,
9 F. G# j- J( y9 [: p( \/ j& Z( t4 s: C( {# N
按下按键I/O接通VCC,输入高电平。
# r$ V) X) {3 C( { ]9 t5 { B- Z) B' {9 h5 k" f
#设计时一般接GND#- k$ ?4 v0 V$ w3 M3 E
: R$ Q( w; B/ {7 Z$ o( G! a& x* F设计思路:采用轮询方式扫描I/O口电平状态,若按键被按下,I/O口为低电平,则LED亮,否则LED不亮。
, k9 r5 L% \' j: _: y' [7 h
6 m2 Z! y4 q4 c1 y# Q0 K; ]7 B1. 新建两个文件,key.c 和 key.h6 n e! w0 U! g
4 e. o& k9 w% }7 z0 k! o' } ~
4 b8 W& D4 u1 V' _0 b- S1 E( K
. Q7 R2 w% H, _& B
2. 在头文件 key.h 添加下面代码:
% U, G G$ B5 z* z8 {" {+ @% k; T5 ~$ t: E8 a* X6 e, k
- #ifndef _KEY_H
0 C# F$ w& M: c5 \. Q$ C# E1 r - #define _KEY_H
: m; _( z! u6 d$ A& l* d! K4 s( t - #include "stm32f10x.h"
3 ?* F( j: I' O# a2 O8 }1 b
$ v6 R) m) C9 \2 U5 V- #define KEY0 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12)
( C3 i- y1 Z; H; ~+ {4 {9 E - 2 x! }! V% y. `- y3 l* ]# ?
- void key_init(void);0 U" i8 K2 X+ z. }: C" j
& q& I7 S5 ]3 G4 e/ Z+ W- #endif;
复制代码
4 O; ~8 R8 E& n* c- ]
! I1 B: f8 k7 X5 [8 V% d
! ~( z: o0 c" h6 S9 \
. \4 `' L6 A4 {8 x/ W# g) e3 F3. 把 key.c 添加到工程中; ~5 |* z- E' x$ r# A4 d# V
* l! y7 h6 ]5 F% W% w
% D0 H, Y/ }5 F
0 A1 A: X% B4 [/ |+ w: ?' h4. 在 key.c 中添加以下代码:
, r) o. ^5 J$ a3 R8 n8 ~
/ Y8 E' r1 J) p) X, z% |* P- #include "key.h"
6 P$ J' w' O1 z
; z; p* z4 E: I- K- I' b: I" j- void key_init(void)& P0 w9 M1 |+ w3 M& p' @
- {
_+ W6 l5 D) s! r7 R9 J$ a - GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体
^4 u: c, o1 a
" Z; V6 y3 X) T" I- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟
2 p) P# |" b& C6 \- \ - / |/ I6 {* y1 ~% f
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //配置引脚6 C4 J/ R7 q: |! D+ [0 A; X
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
# b/ B: V. h8 B- c: Z8 X7 W0 @) X - GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA
- u% @* u* J9 {! L2 K- B - }
复制代码 5 z- \ }; F" G6 {0 ~( ^( g
; h5 K) l) T* d: o* g1 C5 A" A9 R4 T% R& W$ X) @
3 T* H: E5 X# b8 L* r9 Y5. 实现按键轮询控制LED灯亮灭
1 h- K) e' w+ F7 {5 J. R
' [% f; q ^2 g# U1 K' M# _- #include "stm32f10x.h"
4 m, y; F. t7 @- D - #include "delay.h"
- O% u) D3 y5 A9 K( Q - #include "led.h"
( L6 Z' P4 e5 V2 g0 y - #include "tim.h"9 x) l$ Z% P0 R$ M0 A, E7 ^
- #include "key.h"
( d1 Q) {) G& V7 Q, ?& W* p
4 @2 x5 s! J+ S# A- int mian(void)& G* i! U& K% b! Q
- {
4 M' g" U4 a5 B. s- i - delay_init();
# F# U2 k! [8 q; ~9 T5 o* T( M - led_init();
. q- {1 m1 H, t0 Y0 w6 X% E - key_init();
& m; i; V7 ?4 s
# H7 ~4 O- Z1 ~3 O& y- while(1)6 f1 @- Q: E) _' D& ~
- {
9 h* Z6 ?0 T1 g/ h: a4 o0 } - if(KEY0 == 0) {/ b8 c, g! b7 g; @. z* o; E2 B
- delay_ms(20); //按键消抖,时间一般为10-20ms
+ r8 {. @. I7 ^7 S, O7 r! l# F- I$ Y - if(KEY0 == 0) LED_ON; x# Y7 k" i/ F4 b5 I" ]
- }
- g4 `$ C# P& C - else LED_OFF;
; a9 m5 x) q/ g0 A1 t+ n - }
3 v, ]- X0 B4 z! e6 B; \ - }
& J1 c( b8 L; V$ c$ _1 e - D5 a8 r8 r/ v6 s6 f; a7 C
复制代码 4 H9 g0 X' k9 w' {$ _7 k
% d( b8 ?0 ?- h+ i* N! g, i
5 g( P' N) ~/ ?+ }" l
! O9 L O- @. Q" Y: e- _5 {1 D9 {' `库函数相关代码:
6 Y7 ]! J4 x# o0 s
! S+ |* H, d1 H$ m( D( _- /**; ?0 T7 I$ V6 {4 y4 @
- * @brief Reads the specified input port pin.
/ ?7 o- `. i* v# S - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral.) K0 W& H9 X3 N+ J
- * @param GPIO_Pin: specifies the port bit to read.
1 I' N' w1 N7 p5 [ - * This parameter can be GPIO_Pin_x where x can be (0..15).
( }, f6 Z+ M/ r$ ^1 ]) f, M - * @retval The input port pin value.+ t' g" A& j9 h: S0 K1 g: h8 h
- */4 L k9 Q$ q* A2 O% i6 I; [. ]
- uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
* m, \4 {6 I$ }/ s# {1 R; [ - {4 }! X1 {; y+ S/ Y5 s% p" B/ x
- uint8_t bitstatus = 0x00;
6 H1 I* x* U& U2 K1 \ - /* Check the parameters */
/ ~7 z, ]+ {9 y: P3 q( M# W - assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
6 ^6 a1 V7 y- t- D7 g+ z - assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
% u$ N& R! f$ m- A& C - . J5 e. L H: S3 |: y. U
- if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
$ W! o% q7 }2 Z9 F: B2 L7 i - {2 Z# b+ G& J+ j6 Y# M0 {3 w
- bitstatus = (uint8_t)Bit_SET;! G3 ]" `/ V8 X L: c% k
- }
9 G* Y' G. O9 V" p - else2 l& h; U8 _- q
- {: P& a& Y/ f* e( q9 k c. Y1 q' q5 _
- bitstatus = (uint8_t)Bit_RESET;
& E4 ~+ [5 t* ?9 G' \ - }) f' N+ Z9 h y) G
- return bitstatus;! T) S6 O8 Z6 g& e
- }
复制代码 3 L6 M4 a" \8 @ }' X! g- K
' z d2 ?7 S3 Q0 ?手机可以左右滑查看代码
1 N. ?" s B4 e8 m* x0 B3 K( u) C8 R
0 q; K+ ^! f Y# |) v3 L6 ^& @stm32f10x_gpio.c中可以找到上述代码,实际上就是读取GPIOx_IDR寄存器。* [9 I) m7 }0 Y: l; R
& p# i2 B, `; u3 n* x4 M/ B% c
小提示:如果身边没有按键面包板搭电路,可以使用一条杜邦线完成实验,杜邦线的一端接PA12,当另一端接GND时代表“按键”被按下。0 L. A" D9 u) d3 m6 X
! d, l: \3 ?" K& [
( ~1 C4 n; K& y/ q7 k6 V4 N. W# d7 b2 [; ^$ p, T" d8 d
( I6 V# {* i8 W' h
|