|
前面几个实验我们学习了了 STM32 的 IO 口作为输出以及系统时钟的使用,这次实验,通过学习按键来学习如何使用 STM32 的 IO 口作为输入用。我们将利用板载的 4 个按键,来控制板子上的 4 个 LED。 通过本次的实验, 了解到 STM32 的 IO 口作为输入口的方法。实验目标:7 a) G/ L9 L, A# @7 ^$ D+ G 1、了解按键输入的原理。7 X$ E" o1 ]2 ~ 2、了解 STM32 的输入模式配置。 k/ a0 J7 f2 k# F2 N$ a; L ( T& I4 e. c- H: K7 `2 L# ~ 硬件电路设计如图所示
v; H0 A3 U5 T0 _; _7 w" ] 上面的原理图,三个按键分别接到单片机的 PE2、PE3、PE4。9 r5 a; f i7 [9 m9 J$ ^ 按键消抖 按键所用开关为机械弹性开关,当机械触点断开 、闭合时,电压信号 如图示,因此需要做消抖处理。: c- C9 Q" c- A5 A( p
由于机械点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键抖动会引起按键被误读多次。为了确保 CPU 对键的一次闭合仅作一次处理,必须去除按键抖动。一般来说一个简单的按键消抖就是先读取一次按键的状态,如果得到按键按下之后,延时 10ms,再次读取一次按键的状态,如果按键还是按下状态,那么说明按键已经按下。 库函数输入函数 GPIO_ReadInputDataBit ()函数 这个函数是读取一个设置为输出模式时,一个 IO 口的状态值。当读取的 IO 口为 1 的时候,输出 1,当 IO 口输出为 0 的时候,输出 0。5 R* t1 u8 ^+ M5 d0 k 按键 IO 初始化函数配置/ V" L$ T( N. R9 h* N, s x/ O* U7 V void key_init() { GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO/ j( e/ v4 Q% f5 j6 c* P RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); /* 配置 GPIO 的模式和 IO 口 */+ C [& M) V+ _1 p6 _& ` GPIO_InitStructure.GPIO_Pin=K_DOWN|K_LEFT|K_RIGHT;$ ]) M9 V$ a/ o" @. n1 a GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;9 B0 C/ F5 Z5 T. M& Q/ R) | GPIO_Init(GPIOE,&GPIO_InitStructure);, x/ M" I. k, L3 o } 宏定义输入: #define K_DOWN GPIO_Pin_3 //PE3) Y( y6 C' o! ]. F/ x) _5 e #define K_LEFT GPIO_Pin_2 //PE2& w; B3 N5 s+ H& E: n2 | x #define K_RIGHT GPIO_Pin_4 //PE47 m; u4 h" b+ R% k1 _. ` #define k_up GPIO_ReadInputDataBit(GPIOA,K_UP) //获取按键的状态 #define k_down GPIO_ReadInputDataBit(GPIOE,K_DOWN)) H6 `( e0 i5 C# l) ~ #define k_left GPIO_ReadInputDataBit(GPIOE,K_LEFT) #define k_right GPIO_ReadInputDataBit(GPIOE,K_RIGHT) 按键扫描函数5 V" M* z* t( t1 Z6 I* k void keyscan() //按键处理函数 { if(k_down==0) { delay_ms(10); if(k_down==0) {/ P8 t) b, P) U GPIO_Write(GPIOC,(u16)(0xfd));, c0 w# W: c! a; g, ^ }% \) H g- W0 W* J5 {! J7 V: _7 R while(!k_down);! h/ p6 ? I, {9 h) e } if(k_left==0)& w1 \- m/ @& O! ^ {+ u5 w& b- v) w+ ~' T delay_ms(10);0 Y+ A6 i8 @$ P' u* h5 J if(k_left==0) { GPIO_Write(GPIOC,(u16)(0xfb)); } while(!k_left); }# I/ O) q0 s# ?& s% B2 Z" H if(k_right==0) { delay_ms(10);5 L2 n U$ X- w* b/ W( m8 u! z if(k_right==0)/ d* F! b$ l. z- [( ^3 g {8 m6 s0 {( t2 t4 c% y9 w% @: ^ GPIO_Write(GPIOC,(u16)(0xf7)); b# Y" w5 h/ p1 T+ A, X: I3 @ }0 ^/ N, }3 A: k4 Q" N. H+ `' W2 K; ] while(!k_right); } : f: ~! e' F* }+ ^ }2 V6 }* d/ v7 ]0 i# e9 r: w5 M0 @ 这个按键扫描函数只是一个简单的函数,在比较简单的程序里面比较实用,有很明显的缺陷,不支持多按键输入,而且由于使用的是延时消抖,不能充分利用 CPU 资源。大家 如在比较复杂的程序使用按键扫描的话,使用状态机方式的按键扫描,或者零时消抖的按键扫描方式。 int main() { , K. X& i9 ^4 h led_Init(); //LED 初始化, E" ^! \, Q# l key_init(); //按键端口初始化函数 GPIO_Write(GPIOC,(u16)(0xff)); //LED 灭 while(1) T7 z2 o0 q0 d) B: G+ ]" t { keyscan(); //按键处理函数 } 0 s! o1 L8 b- N4 p. g } {3 ^. C+ [4 J t" | 独立按键就先写到这里吧,后面还会分享其它的按键扫描函数。8 G. V/ E z' V& d3 N ; k' B1 R8 U L |
微信公众号
手机版
另外,LZ的硬件是啥板子