之前的点亮小灯实验用到了GPIO的输出模式,但是对于输入模式没有用到,这次小R给小伙伴们介绍GPIO的其中一种输入模式——上拉输入。按键出现在很多的应用场景,按键处理更是一门学问。因此,小R给小伙伴们介绍GPIO的上拉输入模式并简单应用于按键实验中,通过判断按键的状态来控制LED灯的亮灭情况。
2 n) T* a8 q# V* O- p/ ]) C
: N" X0 B2 O7 N7 w首先,需要了解的是:当IO做输入使用时,通过调用函数GPIO_ReadInputDataBit()来读取IO口的电平状态。其次,按键是需要消抖滴。最后,既然是按键实验,就会有按键电路。按键电路如下:( R% g, |) ]1 z2 R J
1 x. d7 D' ]3 t- V0 e
# L9 T' D; u) H5 x
- ?% x, w0 _8 [1 i
电路很简单,将按键接在I/O和GND两端,# W1 P1 ]7 k/ G9 L% |9 [
, B. y! M5 V+ h0 YI/O配置时设置成内部的上拉输入,
% y2 w+ N( F1 x9 m( U! [/ y
: N; i& j1 E0 ]) R这样按下按键接通GND,输入低电平;; ]- q/ P0 V0 \+ W& J
D( g$ n- F1 a8 {
也可以将按键接在I/O和VCC两端,. g3 O# M4 @. L8 R* G+ D4 E
8 j9 J. p" ^: h3 i' W0 X
I/O配置时设置成内部的下拉输入,5 ]6 K7 J) v+ x6 y
9 H/ P! { g1 }- Y& A按下按键I/O接通VCC,输入高电平。5 K6 B* v0 x2 y7 @
& X. Y9 v( J2 _) o, D9 ?$ y
#设计时一般接GND#
) u% b" P8 S. N2 ?7 y! v$ Q: X( W% l8 S X% m
设计思路:采用轮询方式扫描I/O口电平状态,若按键被按下,I/O口为低电平,则LED亮,否则LED不亮。! y; H# T' T) F. T E$ m' }( p
4 ^1 J' x4 N8 W. g/ y2 w' W2 @. X
1. 新建两个文件,key.c 和 key.h
6 a7 {! ^/ B" ?+ o. N5 O1 M
7 t1 n+ o6 Q+ b4 v
% B9 W. g5 A V, G7 ~5 j* i7 J% [% v" h7 j- M3 ~
2. 在头文件 key.h 添加下面代码:
" U4 H- g% @( ?3 R8 M
) Y! r- t" \& }# G2 ?- ~5 w- #ifndef _KEY_H
. x7 D( n4 U9 K7 l$ J6 O - #define _KEY_H
* b. ]; }. L8 W$ q* X - #include "stm32f10x.h"# T' z5 L+ b# {0 r+ M' w3 V
- 8 ~, u, G7 u( F$ C( m' I ~
- #define KEY0 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12)* [7 O$ `5 q6 Z I$ Y/ P1 D
- + M) W! y0 H7 J# n9 [1 _
- void key_init(void);
6 M" L, ^; Z( t. b" o3 m! a( i - + Y4 ?/ ]6 C' G* P
- #endif;
复制代码
& i2 j- U4 Z6 U( U. ]
8 E9 |' H* Y# {
8 N! W: c& B9 x/ j V
1 _3 j: `0 N2 F4 D$ j7 a/ {" T3. 把 key.c 添加到工程中
4 t5 X0 Y9 x& p# L$ V0 E6 F+ h5 ~ R: Z$ m) S- N) K( H3 e
# m2 v- t k9 c% {2 t% T
: o5 o, w$ _" }2 y$ r! F4. 在 key.c 中添加以下代码:
7 V1 N' f: O3 b$ p' t) B! Z0 L6 p7 t! ?) Q9 t; u0 k
- #include "key.h"$ I/ j, v8 F# `3 R
- ! p+ h, K# D+ B$ k) [- T8 f1 N) M( m
- void key_init(void)
+ m; w% `# B& C' M0 {4 G4 k. C - {
6 h" ?, H. D* \7 X/ |. M - GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体$ X }. w$ H# G" r0 u [' S; |
4 p5 k/ o8 b/ L' D& d/ n- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟8 h# l# i0 ^9 F( U5 W2 w2 @
- - k5 X) F2 J: e7 ]. {# h4 \
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //配置引脚
* P' Q$ P* T( s- o - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入; i. ~1 O' g V. P: ~
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA, V: l' X3 ?% I
- }
复制代码
# Z+ f, @( }0 W! [6 O! V
# j: m0 }& H( r# e! f
6 o+ s2 c' w7 i6 U/ U9 N! c) Y* y( f, q* n. t! K D: l/ c
5. 实现按键轮询控制LED灯亮灭
) o1 ]% @5 N, W+ q% G) _6 p4 m6 c% w* L, R1 M1 P6 ~! s
- #include "stm32f10x.h"
, K. j! m" R, S/ q" R - #include "delay.h"
5 @( M6 t! s0 }- v/ w4 I+ V - #include "led.h"
. T$ U; @1 A$ f7 l" O1 }* r5 l - #include "tim.h"
6 q& Y7 y9 F& [# P( T# T7 ^ - #include "key.h"! o3 d y S7 Q4 F
! t: l8 {& s7 D5 C6 G8 [- int mian(void)
2 _2 C h# y, G/ g7 o6 K' { - {+ ^$ E8 }- |0 q4 a9 P# m
- delay_init();
$ o5 o/ N: p. M) @0 g; ]! G - led_init();. f& p, h8 V" _% E) \' t
- key_init();
# e; q3 o4 |+ \: c3 Z
" I9 ~3 l: n" Q- while(1)
" N3 F- c7 x/ b. w/ r2 r - {; @$ _/ Q- X+ S/ N# d
- if(KEY0 == 0) {
V+ @! p1 ?' b - delay_ms(20); //按键消抖,时间一般为10-20ms5 i; G% K* Z% F) Z- y! M
- if(KEY0 == 0) LED_ON;3 n' ]7 B! [2 Q: s
- }1 J2 E0 I+ z3 |* W8 T" I: X- k
- else LED_OFF;/ b) r" C+ ^& r+ ^: [& z, x
- }
8 e b+ W* w( O; e W/ a - }3 ~$ C2 N* |) d9 I; q
& V& {) d% m1 n! @/ g) v# F
复制代码
5 V, D! g* i" D7 Q# @* w e# k l
& @6 h2 v# j" J3 k5 p& v5 Z9 \. x* ~' `! [. i" M
$ V3 B: H- a# F- \& B! V
库函数相关代码:. h/ N; e+ ^3 t0 ^( S9 u
, d- n& G& Z w; P' D; Z' N! |! H1 q
- /**( X; [; h# T. `0 t
- * @brief Reads the specified input port pin.9 a8 g0 R/ Q; u5 Z; s* T
- * @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
/ {3 c4 n2 p* I4 j- ^ - * @param GPIO_Pin: specifies the port bit to read.
6 [5 g) ^5 u) w/ S- t+ F - * This parameter can be GPIO_Pin_x where x can be (0..15).
1 R. L) s' v5 a! ^1 h- b0 q - * @retval The input port pin value.5 [2 H2 i/ T+ j5 K# Z. m
- */
+ b! ?/ V7 J) g - uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)& E% t' l: o* u1 X) W
- {
6 q6 i8 J" [" R' z& K P - uint8_t bitstatus = 0x00;& G, c9 K0 }1 }
- /* Check the parameters */
d9 D4 x$ `) `& b - assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); [: W3 o s9 H9 l$ l" ~3 W- O
- assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); 0 f; }, @5 b( f# L6 a
- $ [. c' n9 l8 j. q- d8 L8 G/ ]
- if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET) F7 }; q, \( G3 }" J! s& ]
- {
$ Q7 m1 ]5 v$ {3 [, ^ - bitstatus = (uint8_t)Bit_SET;/ ^( e& Z3 w J& Q6 q' g
- }
: e# ?/ Z& L3 _. x- ~5 { - else
/ z7 t( r8 U# D |+ ^" L" `, ^ - {( x9 o( A; |# f* f4 v
- bitstatus = (uint8_t)Bit_RESET;
0 ^3 v1 D, h: `+ K9 q" ~5 [ - }1 j/ u( o4 \: m0 [1 b w
- return bitstatus;
k% J: T7 u/ b$ Y' ` - }
复制代码 / j G9 C7 D r# D
* U: x0 s7 N1 X6 }
手机可以左右滑查看代码
3 V# {3 ~" P {, [0 Z' m! \
8 C3 a6 z$ |0 Istm32f10x_gpio.c中可以找到上述代码,实际上就是读取GPIOx_IDR寄存器。- z" T7 l' h! `( u
! }& P& W- }) H+ B! S! C
小提示:如果身边没有按键面包板搭电路,可以使用一条杜邦线完成实验,杜邦线的一端接PA12,当另一端接GND时代表“按键”被按下。
) {, p+ y7 E* D- v" \* c7 A( y( ]1 z5 P/ k! }
1 }2 B3 p0 a2 X/ p
3 G+ B3 G4 E' T+ m
7 i; Z$ S/ @& J8 d, X |