一,达到效果
通过开发板上的 3 个按钮(KEY0 KEY1 WK_UP)来控制板上的 2 个 LED,其中 KEY0 控制 DS0,按一次亮,再按一次,就灭。KEY1 控制 DS1,效 果同 KEY0。WK_UP 按键则同时控制 DS0 和 DS1,按一次,他们的状态就翻转一次。
二,硬件介绍
由图可知KEY0 连接 PC5 、KEY1 连接 PA15 、WK_UP 连接 PA0 ,与此同时KEY0 和 KEY1 是低电平有效的,而 WK_UP 是高电平有效的,除了 KEY1 有上拉电阻(与 JTDI 共用),其他两个都没有上下拉电阻,所以,需要在 STM32 内部设 置上下拉。
三,实验步骤
1,使能按键对应IO口时钟。调用函数:
RCC_APB2PeriphClockCmd();
2,初始化IO模式:上拉/下拉输入。调用函数:
GPIO_Init();
3,扫描IO口电平(库函数/寄存器/位操作)。
四,三种按键扫描模式
1,按键扫描(支持连续按,意思为在规定时间段内,低电平持续时间被分为若干段,若干次被视为按下。)
u8 KEY_Scan(void)
{
if(KEY按下)
{
delay_ms(10); //延时10到20ms,防抖。
if(KEY确实按下)
{
return KEY_Value;
}
return 无效值;
}
}
2,按键扫描(不支持连续按,意思为按下没松开只能算一次。)
u8 KEY_Scan(void)
{
static u8 key_up=1;
if(key_up&& KEY按下)
{
delay_ms(10);//延时,防抖
key_up=0;//标记这次key已经按下
if(KEY确实按下)
{
return KEY_VALUE;
}
}else if(KEY没有按下) key_up=1;
return 没有按下
}
3,按键扫描(两种模式合二为一,如果mode为0,则不支持连续按;如果mode为1,则支持连续按。)
u8 KEY_Scan(void)
{
static u8 key_up=1;
if(mode==1)key_up=1;//支持连续按
if(key_up&& KEY按下)
{
delay_ms(10);//延时,防抖
key_up=0;//标记这次key已经按下
if(KEY确实按下)
{
return KEY_VALUE;
}
}else if(KEY没有按下) key_up=1;
return 没有按下
}
五,相应代码
key.c
#include "key.h"
#include "delay.h"
//按键初始化函数
//PA15 和 PC5 设置成输入
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,
ENABLE);//使能 PORTA,PORTC 时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
//关闭 jtag,使能 SWD,可以用 SWD 模式调试
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 GPIOA15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PC5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化 GPIOC5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 设置成输入,默认下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 GPIOA.0
}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//返回值:
//0,没有任何按键按下
//KEY0_PRES,KEY0 按下
//KEY1_PRES,KEY1 按下
//WKUP_PRES,WK_UP 按下
//注意此函数有响应优先级,KEY0>KEY1>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{
delay_ms(10);//去抖动
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(WK_UP==1)return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;
return 0;// 无按键按下
}
main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h
//ALIENTEK Mini STM32 开发板范例代码 2
//按键输入实验
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司
int main(void)
{
u8 t;
delay_init(); //延时函数初始化
LED_Init(); //初始化与 LED 连接的硬件接口
KEY_Init(); //初始化与按键连接的硬件接口 LED0=0; //点亮 LED while(1)
{
t=KEY_Scan(0); //得到键值
switch(t)
{
case KEY0_PRES:
LED0=!LED0;
break;
case KEY1_PRES:
LED1=!LED1;
break;
case WKUP_PRES:
LED0=!LED0;
LED1=!LED1;
break;
default:
delay_ms(10);
}
}
}
}
补充
static
1,static申明的为局部变量,存储在静态存储区。
2,它在函数调用结束之后,不会被释放。它的值会一直保留下来。
言简意赅为,它有记忆功能,定义局部变量后,函数调用之后,对应的值不会被释放,会被保留,若第二次被调用,不会被重新初始化。