两种按键查询方法,两种方式处理
第一种方法:扫描查询法
优点:无延迟,高灵敏,无中断
思想:也是别人的代码总结出来的,当按键连续读到10个或者20(这个看你的按键多敏感,我的10就够了)低电平,就算按键按下了
//需要循环扫描
u8 IsKey0Down()
{
static u16 iCount = 0;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)
{
iCount ++;
if(iCount>30){
iCount = 0;
return 1;
}
}else{
iCount = 0;
}
return 0;
}
第二种:沿触发进入中断,延时消抖再判断
#if KEY0_SUPPORT_EXTI //支持外部中断的话,如下操作
u8 KEY0_IsDown;//1按下 0没有按下
void EXTI4_IRQHandler()
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)==0)
{
KEY0_IsDown = 1;
EXTI_ClearFlag(EXTI_Line4);
}else{
KEY0_IsDown = 0;
EXTI_ClearFlag(EXTI_Line4);
}
}
#endif
key.c
/****************************************************************************
*按键使用模块说明
*两种:一种需要循环扫描,一种用中断
*使用方法:首先修改h头文件中的宏对按键决定是否需要外部中断,然后修改Key_Init,对哪几个按键初始化
*然后 Key_Init();,然后u8 IsKey0Down() u8 IsKey1Down() u8 IsKey2Down() u8 IsWK_UPDown() (循环扫描)
*或者读u8 KEY0_IsDown; u8 KEY1_IsDown; u8 KEY2_IsDown; u8 WK_UP_IsDown;(中断)
*需要修改的地方,GPIO部分,中断线部分,中断优先级部分,中断函数部分
******************************************************************************/
#include "key.h"
#include "sys.h"
#include "delay.h"
void KEY0_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#if KEY0_SUPPORT_EXTI //支持外部中断的话,如下操作
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//用不同的引脚修改这里
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//该实验按键带下拉电阻,所以这里用下拉
GPIO_Init(GPIOE, &GPIO_InitStructure);
#if KEY0_SUPPORT_EXTI//支持外部中断的话,如下操作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);
EXTI_InitStructure.EXTI_Line = EXTI_Line4;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
}
void KEY1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#if KEY1_SUPPORT_EXTI //支持外部中断的话,如下操作
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//用不同的引脚修改这里
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//该实验按键带下拉电阻,所以这里用下拉
GPIO_Init(GPIOE, &GPIO_InitStructure);
#if KEY1_SUPPORT_EXTI //支持外部中断的话,如下操作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
}
void KEY2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#if KEY2_SUPPORT_EXTI //支持外部中断的话,如下操作
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//用不同的引脚修改这里
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//该实验按键带下拉电阻,所以这里用下拉
GPIO_Init(GPIOE, &GPIO_InitStructure);
#if KEY2_SUPPORT_EXTI //支持外部中断的话,如下操作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);
EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
}
void WK_UP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#if WK_UP_SUPPORT_EXTI //支持外部中断的话,如下操作
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//用不同的引脚修改这里
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//该实验按键带上拉电阻,所以这里用上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);
#if WK_UP_SUPPORT_EXTI //支持外部中断的话,如下操作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开复用
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);//配置中断线
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
}
void Key_Init(void)
{
KEY0_Init();
KEY1_Init();
KEY2_Init();
WK_UP_Init();
}
#if KEY0_SUPPORT_EXTI //支持外部中断的话,如下操作
u8 KEY0_IsDown;//1按下 0没有按下
void EXTI4_IRQHandler()
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)==0)
{
KEY0_IsDown = 1;
EXTI_ClearFlag(EXTI_Line4);
}else{
KEY0_IsDown = 0;
EXTI_ClearFlag(EXTI_Line4);
}
}
#endif
#if KEY1_SUPPORT_EXTI //支持外部中断的话,如下操作
u8 KEY1_IsDown;//1按下 0没有按下
void EXTI3_IRQHandler()
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)==0)
{
KEY1_IsDown = 1;
EXTI_ClearFlag(EXTI_Line3);
}else{
KEY1_IsDown = 0;
EXTI_ClearFlag(EXTI_Line3);
}
}
#endif
#if KEY2_SUPPORT_EXTI //支持外部中断的话,如下操作
u8 KEY2_IsDown;//1按下 0没有按下
void EXTI2_IRQHandler()
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)== 0)
{
KEY2_IsDown = 1;
EXTI_ClearFlag(EXTI_Line2);
}else{
KEY2_IsDown = 0;
EXTI_ClearFlag(EXTI_Line2);
}
}
#endif
#if WK_UP_SUPPORT_EXTI //支持外部中断的话,如下操作
u8 WK_UP_IsDown;//1按下 0没有按下
void EXTI0_IRQHandler()
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1)
{
WK_UP_IsDown = 1;
EXTI_ClearFlag(EXTI_Line0);
}else{
WK_UP_IsDown = 0;
EXTI_ClearFlag(EXTI_Line0);
}
}
#endif
//需要循环扫描
u8 IsKey0Down()
{
static u16 iCount = 0;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)
{
iCount ++;
if(iCount>30){
iCount = 0;
return 1;
}
}else{
iCount = 0;
}
return 0;
}
u8 IsKey1Down()
{
static u16 iCount = 0;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)
{
iCount ++;
if(iCount>30){
iCount = 0;
return 1;
}
}else{
iCount = 0;
}
return 0;
}
u8 IsKey2Down()
{
static u16 iCount = 0;
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0)
{
iCount ++;
if(iCount>30){
iCount = 0;
return 1;
}
}else{
iCount = 0;
}
return 0;
}
u8 IsWK_UPDown()
{
static u16 iCount = 0;
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1)
{
iCount ++;
if(iCount>30){
iCount = 0;
return 1;
}
}else{
iCount = 0;
}
return 0;
}
key.h
#ifndef __KEY_H_
#define __KEY_H_
#include "stm32f10x.h"
//如果按键用外部中断,则修改下面对应按键的宏值为1
#define KEY0_SUPPORT_EXTI 1
#define KEY1_SUPPORT_EXTI 1
#define KEY2_SUPPORT_EXTI 1
#define WK_UP_SUPPORT_EXTI 1
extern u8 KEY0_IsDown;
extern u8 KEY1_IsDown;
extern u8 KEY2_IsDown;
extern u8 WK_UP_IsDown;
void KEY0_Init(void);
void KEY1_Init(void);
void KEY2_Init(void);
void WK_UP_Init(void);
void Key_Init(void);
u8 IsKey0Down(void);
u8 IsKey1Down(void);
u8 IsKey2Down(void);
u8 IsWK_UPDown(void);
#endif
这里修改宏就可以打开和关闭按键的中断
|