打印
[STM32]

为什么我使用STM32外部中断做按键,很难实现双击?

[复制链接]
908|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
基本上只能实现单击,快速单击两下,只响应一次,使用的是下面这种键盘,每根线一端接地,直接连端口




代码如下
GPIO.H

#ifndef __GPIO_H
#define __GPIO_H

#include "include.h"


//板载LED灯
#define OnBoardLedPort          GPIOC
#define OnBoardLedPin                        GPIO_Pin_13

//蜂鸣器
#define BeepPort                                   GPIOC
#define BeepPin                                                GPIO_Pin_15

//OLED屏幕
#define OLED1RCC                    RCC_APB2Periph_GPIOB
#define OLED1Port                         GPIOB
#define OLED1_SCL_Pin          GPIO_Pin_10
#define OLED1_SDA_Pin          GPIO_Pin_11


//按键
#define KeyRCC    RCC_APB2Periph_GPIOA
#define KeyPort   GPIOA
#define K1Pin                        GPIO_Pin_0
#define K2Pin                        GPIO_Pin_1
#define K3Pin                        GPIO_Pin_2
#define K4Pin                        GPIO_Pin_3
#define K5Pin                        GPIO_Pin_4
#define K6Pin                        GPIO_Pin_5
#define K7Pin                        GPIO_Pin_6
#define K8Pin                        GPIO_Pin_7


#endif  //__GPIO_H

MAIN.H



#include "include.h"


#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "bmp.h"
#include "rocket.h"

#include "gpio.h"

#include "it.h"

void NVIC_INIT(void);
void GPIO_INIT(void);
void SimpleBeep(void);

//KEY* K1 = KeyMap(GPIOA,GPIO_Pin_8,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K2 = KeyMap(GPIOB,GPIO_Pin_12,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K3 = KeyMap(GPIOB,GPIO_Pin_13,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K4 = KeyMap(GPIOB,GPIO_Pin_14,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K5 = KeyMap(GPIOB,GPIO_Pin_15,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K6 = KeyMap(GPIOC,GPIO_Pin_13,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K7 = KeyMap(GPIOC,GPIO_Pin_14,GPIO_Mode_IPU,GPIO_Speed_50MHz);
//KEY* K8 = KeyMap(GPIOC,GPIO_Pin_15,GPIO_Mode_IPU,GPIO_Speed_50MHz);

int count = 0;

int main(void)
{
               
                u8 t=' ';
       
                NVIC_INIT();
       
                GPIO_INIT();
       
                delay_init();
                OLED_Init();
                OLED_ColorTurn(0);//0������ʾ��1 ��ɫ��ʾ
                OLED_DisplayTurn(0);//0������ʾ 1 ��Ļ��ת��ʾ
               
       
                GPIO_ResetBits(GPIOB,GPIO_Pin_12);
       
                SimpleBeep();
       
                while(1)
                {

                }

}

void GPIO_INIT(void)
{
               
                //打开端口
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
               
       
        //使用EXTI需要开AFIO(复用IO)
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
       
       
                //蜂鸣器PA1,送方波,遇低电平触发
                StdSetMode(BeepPort, BeepPin,GPIO_Mode_Out_PP,GPIO_Speed_2MHz,1);
       
                //板载LED,PC13,LED接VCC,所以需要低电平触发
                StdSetMode(OnBoardLedPort, OnBoardLedPin,GPIO_Mode_Out_PP,GPIO_Speed_2MHz,1);
       
               
                //按键(上拉模式,置1)
                StdSetMode(KeyPort, K1Pin|K2Pin|K3Pin|K4Pin|K5Pin|K6Pin|K7Pin|K8Pin,GPIO_Mode_IPU,GPIO_Speed_10MHz,1);
               
                //外部中断
                StdSetEXTI(GPIO_PortSourceGPIOA,GPIO_PinSource0,
                                                                                EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4 | EXTI_Line5 | EXTI_Line6 | EXTI_Line7,
                                                                                EXTI_Mode_Interrupt,EXTI_Trigger_Falling);
                                                                               
                                                                               
               
}

void NVIC_INIT()
{
        StdSetNVIC(EXTI0_IRQn,0x0f,0x0f);
        StdSetNVIC(EXTI1_IRQn,0x0f,0x0f);
        StdSetNVIC(EXTI2_IRQn,0x0f,0x0f);
        StdSetNVIC(EXTI3_IRQn,0x0f,0x0f);
        StdSetNVIC(EXTI4_IRQn,0x0f,0x0f);
        StdSetNVIC(EXTI9_5_IRQn,0x0f,0x0f);
}






ROCKET.H


#include "include.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"



#include "rocket.h"

#include "delay.h"



void StdSetMode(GPIO_TypeDef *      GPIOx ,
                                                                uint16_t                                                 Pin,               
                                                                GPIOMode_TypeDef                 mode,
                                                                GPIOSpeed_TypeDef         speed,
                                                                char                                                                set)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
        GPIO_InitStructure.GPIO_Pin         = Pin;         
        GPIO_InitStructure.GPIO_Mode         = mode;
        GPIO_InitStructure.GPIO_Speed = speed;
       
        GPIO_Init(GPIOx, &GPIO_InitStructure);
        if(set){
                        GPIO_SetBits(GPIOx,Pin);
        }else{
                        GPIO_ResetBits(GPIOx,Pin);
        }
       
}


void StdSetEXTI(uint8_t GPIO_PortSourceGPIOx,
                                                                uint8_t GPIO_PinSourceN,
                                                                uint32_t EXTI_LineN,
                                                                EXTIMode_TypeDef  EXTI_Mode_Interrupt,    //中断或事件
                                                                EXTITrigger_TypeDef  EXTI_Trigger_Falling //上升沿或下降沿触发
)
{
                EXTI_InitTypeDef EXTIx;
       
                GPIO_EXTILineConfig(GPIO_PortSourceGPIOx, GPIO_PinSourceN);

                EXTIx.EXTI_Line                 = EXTI_LineN;
                EXTIx.EXTI_Mode                 = EXTI_Mode_Interrupt;  
                EXTIx.EXTI_Trigger         = EXTI_Trigger_Falling;
                EXTIx.EXTI_LineCmd         = ENABLE;  
                EXTI_Init(&EXTIx);
       
       
}



void StdSetNVIC(uint8_t EXTIn_IRQn,uint8_t PPri,uint8_t SubPri)
{
        NVIC_InitTypeDef   NVICx;
        NVICx.NVIC_IRQChannel = EXTIn_IRQn;
        NVICx.NVIC_IRQChannelPreemptionPriority = PPri;
        NVICx.NVIC_IRQChannelSubPriority = SubPri;
        NVICx.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVICx);
}
KEY* KeyMap(GPIO_TypeDef* GPIO,uint16_t Pin,GPIOMode_TypeDef Mode,GPIOSpeed_TypeDef Speed)
{
        KEY* k;
        k->GPIO = GPIO;
        k->Pin         = Pin;
        k->Mode = Mode;
        k->Speed = Speed;
        return k;
};

//无源指无振荡源,需要频率2K-5K方波去驱动
//用延时产生1秒时长的,频率为5K的方波
//总时长1s,频率5k,即每秒翻转5K次,每次时长200us
//i=1000         -> 2*10^5us = 200 000 us = 200 ms = 1/5秒 = 0.2 秒
//i=500         -> 0.1 秒
//蜂鸣伴随闪灯
void SimpleBeep(void)
{
        int i;
        for(i=0; i<500; i++)
        {
                        GPIO_ResetBits(BeepPort,BeepPin);
                        GPIO_ResetBits(OnBoardLedPort,OnBoardLedPin);
                        delay_us(100);
                        GPIO_SetBits(BeepPort,BeepPin);
                        GPIO_SetBits(OnBoardLedPort,OnBoardLedPin);
                        delay_us(100);
        }
}
IT.H
#ifndef __IT_H
#define __IT_H

#include "include.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
#include "delay.h"
#include "oled.h"
#include "gpio.h"
#include "rocket.h"

extern int count;

//K1中断
void EXTI0_IRQHandler(void)
{   
       
                if(EXTI_GetITStatus(EXTI_Line0)!=RESET){
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K1Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K1Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line0);
                       
                }
               
}

void EXTI1_IRQHandler(void)
{   
       
                if(EXTI_GetITStatus(EXTI_Line1)!=RESET){
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K2Pin)==0)
                        {
                                count-=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K2Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line1);
                }
}

void EXTI2_IRQHandler(void)
{   
       
                if(EXTI_GetITStatus(EXTI_Line2)!=RESET){
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K3Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K3Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line2);
                }
};

void EXTI3_IRQHandler(void)
{   
       
                if(EXTI_GetITStatus(EXTI_Line3)!=RESET)
                {
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K4Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K4Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line3);
                }
};

void EXTI4_IRQHandler(void)
{   
       
                if(EXTI_GetITStatus(EXTI_Line4)!=RESET)
                {
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K5Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K5Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line4);
                }
};
               
void EXTI9_5_IRQHandler(void)
{   
       
                if(EXTI_GetITStatus(EXTI_Line5)!=RESET)
                {
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K6Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K6Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line5);
                }
               
                if(EXTI_GetITStatus(EXTI_Line6)!=RESET)
                {
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K7Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K7Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line6);
                }
               
                if(EXTI_GetITStatus(EXTI_Line7)!=RESET)
                {
                        delay_ms(50);
                       
                        if(GPIO_ReadInputDataBit(KeyPort,K8Pin)==0)
                        {
                                count+=1;
                                OLED_ShowNum(1,1,count,3,16,1);
                                OLED_Refresh();
                                SimpleBeep();
                                GPIO_SetBits(KeyPort,K8Pin);
                        }
                        EXTI_ClearITPendingBit(EXTI_Line7);
                }
};


#endif  // __IT_H



使用特权

评论回复

相关帖子

沙发
lumia710| | 2021-2-17 11:04 | 只看该作者
看标题就知道是中断里做延时

使用特权

评论回复
板凳
nuaabob| | 2021-2-17 18:54 | 只看该作者
两次进入中断触发事件行不行?再加个定时器判断双击时间间隔?

使用特权

评论回复
地板
gx_huang| | 2021-2-17 19:20 | 只看该作者
软件架构太差,在中断里有较长延时,你想让MCU自杀呀

使用特权

评论回复
5
gxs64| | 2021-2-17 22:11 | 只看该作者
中断的用法是:一般设置相应标志,尽快从中断中出来,在主程序中判标志。

使用特权

评论回复
6
ayb_ice| | 2021-2-18 08:30 | 只看该作者
我最反对按键用中断的,因为扫键根本花不了多少时间,资源,中断去抖还麻烦,如果做长,短,连按,这些还是需要算法来处理,典型的简单问题复杂化,还浪费中断这宝贵资源

使用特权

评论回复
7
wasonguo| | 2021-2-18 15:23 | 只看该作者
可否画个流程图?

使用特权

评论回复
8
sjnh| | 2021-2-18 15:27 | 只看该作者
本帖最后由 sjnh 于 2021-2-18 15:29 编辑

双击是你软件处理的事,退出中断做标志,并且有定时判断两次间隔,按键要做防抖处理

使用特权

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

本版积分规则

17

主题

63

帖子

2

粉丝