打印
[应用相关]

按键的模块化,低延时,高灵敏

[复制链接]
1084|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
usysm|  楼主 | 2023-10-17 17:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
两种按键查询方法,两种方式处理
第一种方法:扫描查询法
优点:无延迟,高灵敏,无中断
思想:也是别人的代码总结出来的,当按键连续读到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

这里修改宏就可以打开和关闭按键的中断

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

57

主题

4075

帖子

3

粉丝