前面几个实验我们学习了了 STM32 的 IO 口作为输出以及系统时钟的使用,这次实验,通过学习按键来学习如何使用 STM32 的 IO 口作为输入用。我们将利用板载的 4 个按键,来控制板子上的 4 个 LED。 通过本次的实验, 了解到 STM32 的 IO 口作为输入口的方法。实验目标: 1、了解按键输入的原理。; H! f7 w6 B9 b7 J 2、了解 STM32 的输入模式配置。 硬件电路设计如图所示2 d* I$ ?( R) {; Z $ J+ B" U' x1 T5 O8 d5 B 上面的原理图,三个按键分别接到单片机的 PE2、PE3、PE4。" }: r# m; Y; M, Z2 L' j& _2 n2 s 按键消抖$ l( I( h) Q8 G 按键所用开关为机械弹性开关,当机械触点断开 、闭合时,电压信号 如图示,因此需要做消抖处理。0 `; R/ b) [ T/ k: F 由于机械点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键抖动会引起按键被误读多次。为了确保 CPU 对键的一次闭合仅作一次处理,必须去除按键抖动。一般来说一个简单的按键消抖就是先读取一次按键的状态,如果得到按键按下之后,延时 10ms,再次读取一次按键的状态,如果按键还是按下状态,那么说明按键已经按下。, n# o4 r7 [& h0 e ) h- r" J# X# n) u4 | 库函数输入函数 GPIO_ReadInputDataBit ()函数 这个函数是读取一个设置为输出模式时,一个 IO 口的状态值。当读取的 IO 口为 1 的时候,输出 1,当 IO 口输出为 0 的时候,输出 0。" U! F. [- A' V2 b# c. F 按键 IO 初始化函数配置 void key_init() 0 N$ p4 j" U+ J% W5 z9 h {& \2 r1 {% q5 J5 T- c GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);* k3 r, J$ m: l9 H: R/ g- J /* 配置 GPIO 的模式和 IO 口 */' w) T/ l. L* a) v GPIO_InitStructure.GPIO_Pin=K_DOWN|K_LEFT|K_RIGHT;# J! E: R% A; e9 A( N GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOE,&GPIO_InitStructure); }( b+ N: U6 |+ B 宏定义输入: #define K_DOWN GPIO_Pin_3 //PE3 #define K_LEFT GPIO_Pin_2 //PE2: g7 i1 m3 A9 F9 D: }# i1 J #define K_RIGHT GPIO_Pin_4 //PE4 #define k_up GPIO_ReadInputDataBit(GPIOA,K_UP) //获取按键的状态- O9 n7 @& y; J0 A% ^, l #define k_down GPIO_ReadInputDataBit(GPIOE,K_DOWN): u! N# w' S) i/ j6 g; d( ]5 ~ #define k_left GPIO_ReadInputDataBit(GPIOE,K_LEFT) #define k_right GPIO_ReadInputDataBit(GPIOE,K_RIGHT) `2 C" j% J- ~% F( C. a8 P, G 按键扫描函数 void keyscan() //按键处理函数6 L7 G/ m& @# Q1 @+ ^& w1 z { if(k_down==0)" t0 k) O; Q' P) o3 I) V { delay_ms(10);; f$ c% H: D% T9 R9 j if(k_down==0) {" k( _9 Q, G5 S- N8 U) W GPIO_Write(GPIOC,(u16)(0xfd)); }1 H! C g' F4 F# f. t" P6 k @ u while(!k_down); }9 D2 m# }+ o! O( E) T if(k_left==0)1 q# r6 ^# y# Y! @ { delay_ms(10);, c1 G) W9 E( A1 l2 f if(k_left==0) { GPIO_Write(GPIOC,(u16)(0xfb)); } while(!k_left);( l; e2 }0 A0 b# _ } if(k_right==0) { delay_ms(10);0 g0 ~' i9 {7 ?+ E; m if(k_right==0)3 Z. e! E% [9 l! `! \' q! [ { GPIO_Write(GPIOC,(u16)(0xf7));5 e8 D" f3 Z' J# Y+ ^ }% E6 R; @9 q' A+ l while(!k_right); } } 这个按键扫描函数只是一个简单的函数,在比较简单的程序里面比较实用,有很明显的缺陷,不支持多按键输入,而且由于使用的是延时消抖,不能充分利用 CPU 资源。大家 如在比较复杂的程序使用按键扫描的话,使用状态机方式的按键扫描,或者零时消抖的按键扫描方式。, F/ \( Q, v3 E |+ a7 }6 J! U ' z. z' }# ?1 G int main() { led_Init(); //LED 初始化. B u2 w, y' m key_init(); //按键端口初始化函数0 R8 a) R; ?1 D7 o/ F( f" _ GPIO_Write(GPIOC,(u16)(0xff)); //LED 灭5 |$ J. m% j9 L8 D' ^2 n while(1)8 @: D1 h0 d& f: s. i& o* c2 L { keyscan(); //按键处理函数 2 o p: t. H7 [. y } } s7 s! e* B" R3 A7 L/ T 独立按键就先写到这里吧,后面还会分享其它的按键扫描函数。1 D* y; E$ E1 J2 Q4 U" i 5 f8 F7 C; g" |* P& V |
另外,LZ的硬件是啥板子