【STM32F429单片机学习】单片机学习之按键实验
按键实验文件组成
一、key.c(GPIO口的初始化、KEY的基本功能)
分析代码(颜色一样的为一步)
引入KEY、delay头文件(有声明与函数)
#include "key.h"
#include "delay.h"
定义按键初始化函数(其实就是初始化IO口同LED的方法)
void KEY_Init(void)
{
定义GPIO的结构体,因为HAL_GPIO_Init的入口参数为两个均为指针,其中之一为某个GPIO,另一个为结构体,结构体包含着pin的模式
GPIO_InitTypeDef GPIO_Initure;
使用某个外设一定要打开其时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟
__HAL_RCC_GPIOH_CLK_ENABLE(); //开启GPIOH时钟
设定IO 的输出模式等,因为这是按键实验所以要MODE为输入,KEY有时候低电平有效,有的时候高电平有效,这要看原理图来确定其工作方式,查阅原理图后,我将IO设置如下
GPIO_Initure.Pin=GPIO_PIN_0; //PA0
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_13; //PC13
GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}
在我们初始化IO口,接下来就要设定他的具体功能了,初始化IO我认为好比给汽车点火,而定义功能函数(如下的scan函数)就好比开车出发,首先我们要想到某个KEY按下后,单片机怎么检测到是哪个KEY,仔细想想应该是通过扫描(scan)某个IO口的高低电平来实现,好比当KEY1按下后对应得IO有电平的变化,让单片机知道是那个KEY 按下了
u8 KEY_Scan(u8 mode)
{
设置静态参数(无符号8位整数u8,其范围0-255,所以不用u16 u32),且返回值也为u8,key_up=1,他的值在循环进入程序中不会改变,static(静态),我们把这个key_up=1定义为一个标识符,用来 标定按键未能按下
static u8 key_up=1; //按键松开标志
有两种模式mode=0 or 1 选择即可,我们这次mode=0
if(mode==1)key_up=1; //支持连按
这里的KEY0==1等,为宏定义其实背后就是一个HAL的READ函数可以读取IO口的高低电平(0 OR 1),这里在.h文件中定义,此代码为某个按键按下后也就是生效后,与我们的按键表示符 key_up=1 与一下,成立就表示按下 key_up=0,若无则 return 0
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
delay_ms(10);
key_up=0;
如果有按键按下那么判断一下到底哪个IO是什么样的电平,来返回一个事件符就是 return KEY0_PRES,首先KEY0_PRES在.h中定义为宏常量目的是建立起4个事件(哪个按钮被按下了),然后在mian.c中与swtich case 结合起来,执行对应的事件。
if(KEY0==0) return KEY0_PRES;
else if(KEY1==0) return KEY1_PRES;
else if(KEY2==0) return KEY2_PRES;
else if(WK_UP==1) return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
return 0; //无按键按下
}
二、led.c(GPIO口的初始化、LED灯的基本功能)
请看LED跑马灯实验讲解
三、key.h
保护头文件
#ifndef _KEY_H
#define _KEY_H
#include "sys.h"
定义宏变量也就是 HAL_GPIO_ReadPin读取的参数传递给KEY0 ,看到这是不是对KEY.C文件中的操作就明白了
#define KEY0 HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3) //KEY0按键PH3
#define KEY1 HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2) //KEY1按键PH2
#define KEY2 HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2按键PC13
#define WK_UP HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //WKUP按键PA0
定义宏常亮,就是为了分成四个实验 到时候与swtich case 联动
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4
声明你在.c文件中的函数
void KEY_Init(void);
u8 KEY_Scan(u8 mode);
#endif
四、led.h
请看LED跑马灯实验讲解
五、main.c(GPIO口的初始化、LED灯的基本功能)
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
定义主函数
int main(void)
{
调用函数
u8 key;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
构造一个死循环
while(1)
{
key是一个返回值 switch通过判断KEY的值来选择事件
key=KEY_Scan(0); //按键扫描
switch(key)
{
case WKUP_PRES: //控制LED0,LED1互斥点亮
LED1=!LED1;
LED0=!LED1;
break;
case KEY2_PRES: //控制LED0翻转
LED0=!LED0;
break;
case KEY1_PRES: //控制LED1翻转
LED1=!LED1;
break;
case KEY0_PRES: //同时控制LED0,LED1翻转
LED0=!LED0;
LED1=!LED1;
break;
}
delay_ms(10);
}
}

