工程项目结构:
其中画红色方框部分为主要函数实现功能
key.h
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#include "DELAY/Delay.h"
/*
keyval = 0000 0000
KEY_UP = 0000 0001
KEY_DOWN = 0000 0010
KEY_ALL = 0000 0011
*/
typedef enum
{
KEY_NO = 0x00, //没有按键按下
KEY_UP = 0x01, //UP键按下
KEY_DOWN = 0x02, //DOWN键按下
KEY_ALL = 0x03 //同时按下
}KEY_VALUE;
typedef enum
{
KEY_PRESS = 0x01, //按下按键
KEY_RELEASE = 0x02 //释放按键
}KEY_MODE;
#define KEY_UP_PIN GPIO_Pin_3 //宏定义KEYUP引脚
#define KEY_DOWN_PIN GPIO_Pin_4 //宏定义KEYDWON引脚
void initKey(void);
u8 getKeyValue(u8 mode);
#endif
key.c
#include "KEY/key.h"
/**
* 功能:初始化按键
* 参数:None
* 返回值:None
*/
void initKey(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //使能GPIO时钟
GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN|KEY_DOWN_PIN; //设置按键对应引脚 UP->PE3, DOWN->PE4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure); //设置生效
}
/**
* 功能:获取按键值,支持同时按下,按键释放后生效
* 参数:mode:用于指定按键触发方式,参数可选:KEY_PRESS,KEY_RELEASE
* 返回值:返回按键值,当同时按下时,返回值是 KEY_UP|KEY_DOWN 即0x03
*/
u8 getKeyValue(u8 mode)
{
u8 keyval = 0;
// 不改变其它位的情况下只对某一位置用 | 运算
// 不改变其它位的情况下只对某一位清零用 & 运算
if(mode == KEY_PRESS) //按下按键即可生效
{
/**************检测UP键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_UP;
}else
{
keyval &= ~KEY_UP;
}
}else
{
keyval &= ~KEY_UP; //没有按下 对应位清零
}
/**************检测DOWN键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_DOWN;
}else
{
keyval &= ~KEY_DOWN;
}
}else
{
keyval &= ~KEY_DOWN; //没有按下 对应位清零
}
}else if(mode == KEY_RELEASE) //松开按键生效
{
/**************检测UP键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_UP;
}else
{
keyval &= ~KEY_UP;
}
}else
{
keyval &= ~KEY_UP; //没有按下 对应位清零
}
/**************检测DOWN键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_DOWN;
}else
{
keyval &= ~KEY_DOWN;
}
}else
{
keyval &= ~KEY_DOWN; //没有按下 对应位清零
}
while(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0 || GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0); //等待按键释放
}
return keyval;
}
main.c
#include "LED/LED.h"
#include "stm32f10x.h"
#include "DELAY/Delay.h"
#include "KEY/key.h"
int main(void)
{
u16 time = 500; //LED闪烁时间 开机默认500ms
u8 keyvalue;
initSysTick(); //初始化Systick
initLED(); //初始化LED
initKey(); //初始化按键
while (1)
{
keyvalue= getKeyValue(KEY_PRESS); //获取键值
switch(keyvalue)
{
case KEY_UP: time = 50; break;//50ms频率闪烁
case KEY_DOWN: time = 2000; break;//2s频率闪烁
case KEY_ALL: blinkLED(10,50,500); break;//同时按下时,亮50ms灭500ms闪烁10次
default: break;//没按下不做任何处理
}
blinkLED(1,time,time);
}
}
工程项目结构:
其中画红色方框部分为主要函数实现功能
key.h
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#include "DELAY/Delay.h"
/*
keyval = 0000 0000
KEY_UP = 0000 0001
KEY_DOWN = 0000 0010
KEY_ALL = 0000 0011
*/
typedef enum
{
KEY_NO = 0x00, //没有按键按下
KEY_UP = 0x01, //UP键按下
KEY_DOWN = 0x02, //DOWN键按下
KEY_ALL = 0x03 //同时按下
}KEY_VALUE;
typedef enum
{
KEY_PRESS = 0x01, //按下按键
KEY_RELEASE = 0x02 //释放按键
}KEY_MODE;
#define KEY_UP_PIN GPIO_Pin_3 //宏定义KEYUP引脚
#define KEY_DOWN_PIN GPIO_Pin_4 //宏定义KEYDWON引脚
void initKey(void);
u8 getKeyValue(u8 mode);
#endif
key.c
#include "KEY/key.h"
/**
* 功能:初始化按键
* 参数:None
* 返回值:None
*/
void initKey(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //使能GPIO时钟
GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN|KEY_DOWN_PIN; //设置按键对应引脚 UP->PE3, DOWN->PE4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure); //设置生效
}
/**
* 功能:获取按键值,支持同时按下,按键释放后生效
* 参数:mode:用于指定按键触发方式,参数可选:KEY_PRESS,KEY_RELEASE
* 返回值:返回按键值,当同时按下时,返回值是 KEY_UP|KEY_DOWN 即0x03
*/
u8 getKeyValue(u8 mode)
{
u8 keyval = 0;
// 不改变其它位的情况下只对某一位置用 | 运算
// 不改变其它位的情况下只对某一位清零用 & 运算
if(mode == KEY_PRESS) //按下按键即可生效
{
/**************检测UP键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_UP;
}else
{
keyval &= ~KEY_UP;
}
}else
{
keyval &= ~KEY_UP; //没有按下 对应位清零
}
/**************检测DOWN键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_DOWN;
}else
{
keyval &= ~KEY_DOWN;
}
}else
{
keyval &= ~KEY_DOWN; //没有按下 对应位清零
}
}else if(mode == KEY_RELEASE) //松开按键生效
{
/**************检测UP键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_UP;
}else
{
keyval &= ~KEY_UP;
}
}else
{
keyval &= ~KEY_UP; //没有按下 对应位清零
}
/**************检测DOWN键函数段********************/
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第一次检测时按下
{
Delay_ms(10); //延时去抖
if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第二次检测还为零则可以确定按键按下
{
keyval |= KEY_DOWN;
}else
{
keyval &= ~KEY_DOWN;
}
}else
{
keyval &= ~KEY_DOWN; //没有按下 对应位清零
}
while(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0 || GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0); //等待按键释放
}
return keyval;
}
main.c
#include "LED/LED.h"
#include "stm32f10x.h"
#include "DELAY/Delay.h"
#include "KEY/key.h"
int main(void)
{
u16 time = 500; //LED闪烁时间 开机默认500ms
u8 keyvalue;
initSysTick(); //初始化Systick
initLED(); //初始化LED
initKey(); //初始化按键
while (1)
{
keyvalue= getKeyValue(KEY_PRESS); //获取键值
switch(keyvalue)
{
case KEY_UP: time = 50; break;//50ms频率闪烁
case KEY_DOWN: time = 2000; break;//2s频率闪烁
case KEY_ALL: blinkLED(10,50,500); break;//同时按下时,亮50ms灭500ms闪烁10次
default: break;//没按下不做任何处理
}
blinkLED(1,time,time);
}
}
举报