前面几个实验我们学习了了 STM32 的 IO 口作为输出以及系统时钟的使用,这次实验,通过学习按键来学习如何使用 STM32 的 IO 口作为输入用。我们将利用板载的 4 个按键,来控制板子上的 4 个 LED。 通过本次的实验, 了解到 STM32 的 IO 口作为输入口的方法。实验目标: 1、了解按键输入的原理。: O5 C* P9 p/ A6 U0 C8 R 2、了解 STM32 的输入模式配置。 7 N# |7 N; ~- p& d; K4 A: ^% D 硬件电路设计如图所示 ; o0 n( w) H" a+ _ 上面的原理图,三个按键分别接到单片机的 PE2、PE3、PE4。 按键消抖1 M7 `4 X" C, A) d; M, k0 r9 W 按键所用开关为机械弹性开关,当机械触点断开 、闭合时,电压信号 如图示,因此需要做消抖处理。$ n# [& y5 f$ F8 x, K 7 Y: ~1 ] h) J0 g% a) J+ [: H! Q# K/ z( K 5 R" `/ r' V/ Z% i 由于机械点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键抖动会引起按键被误读多次。为了确保 CPU 对键的一次闭合仅作一次处理,必须去除按键抖动。一般来说一个简单的按键消抖就是先读取一次按键的状态,如果得到按键按下之后,延时 10ms,再次读取一次按键的状态,如果按键还是按下状态,那么说明按键已经按下。 库函数输入函数0 P! K3 K+ q5 D9 d7 p! e6 } GPIO_ReadInputDataBit ()函数 这个函数是读取一个设置为输出模式时,一个 IO 口的状态值。当读取的 IO 口为 1 的时候,输出 1,当 IO 口输出为 0 的时候,输出 0。4 P' j; i. Y, }4 t4 f 按键 IO 初始化函数配置5 G8 `* D7 ^( y" p. E! D! Y void key_init() $ e0 k! O) k `6 H; u# ?: X {5 S) i: d) n& I) H3 `2 P GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO6 E3 k& Q( p" z" Q/ [0 y RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); /* 配置 GPIO 的模式和 IO 口 */& Z& [) U5 m/ h: P( t+ N$ J GPIO_InitStructure.GPIO_Pin=K_DOWN|K_LEFT|K_RIGHT; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;2 z9 v9 W: ]2 Z( d' w. X2 g GPIO_Init(GPIOE,&GPIO_InitStructure); }4 N3 o- P9 i" x6 W6 B 宏定义输入: #define K_DOWN GPIO_Pin_3 //PE3 #define K_LEFT GPIO_Pin_2 //PE2 #define K_RIGHT GPIO_Pin_4 //PE4 #define k_up GPIO_ReadInputDataBit(GPIOA,K_UP) //获取按键的状态 #define k_down GPIO_ReadInputDataBit(GPIOE,K_DOWN) #define k_left GPIO_ReadInputDataBit(GPIOE,K_LEFT) #define k_right GPIO_ReadInputDataBit(GPIOE,K_RIGHT)/ s- Y8 x1 w5 q% Q 按键扫描函数! @! M; E( \* x! s void keyscan() //按键处理函数5 G, Y( W4 O% M7 |- M {8 l: E: I/ E" i. J' A6 M; T) a6 V if(k_down==0) {1 O& J* U0 @ F3 c delay_ms(10); if(k_down==0) { GPIO_Write(GPIOC,(u16)(0xfd)); } while(!k_down); } if(k_left==0)0 ?8 ?9 J# i2 ~4 {9 h { delay_ms(10); if(k_left==0)" k0 f% Z# D0 y3 w4 I# I! O { ~: B( d3 _% Q# Q! ]2 h GPIO_Write(GPIOC,(u16)(0xfb)); } while(!k_left);5 W, p4 \: [4 a! N& _) t: I } if(k_right==0) {! V: I; i! |) ~6 y delay_ms(10);5 u; }" d. I0 g8 r4 K if(k_right==0) { GPIO_Write(GPIOC,(u16)(0xf7)); }' {& c9 V: a6 I# q2 O; k while(!k_right);" K. q3 |- g [+ s/ E$ i+ L ? } 3 G+ _" N; m1 h' m } 这个按键扫描函数只是一个简单的函数,在比较简单的程序里面比较实用,有很明显的缺陷,不支持多按键输入,而且由于使用的是延时消抖,不能充分利用 CPU 资源。大家 如在比较复杂的程序使用按键扫描的话,使用状态机方式的按键扫描,或者零时消抖的按键扫描方式。 int main() { " H1 f+ G: B: f6 {' P led_Init(); //LED 初始化$ |) V4 n: G- v0 G' C+ n# H3 k key_init(); //按键端口初始化函数 GPIO_Write(GPIOC,(u16)(0xff)); //LED 灭 p. Z$ G+ u; q* v while(1) { ( L2 G( E7 M6 v, K) U4 H keyscan(); //按键处理函数 } }1 x; `0 n1 h6 G+ } 独立按键就先写到这里吧,后面还会分享其它的按键扫描函数。 |
另外,LZ的硬件是啥板子