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

[复制链接]
1254|7
 楼主| vincent.liu 发表于 2021-2-16 15:52 | 显示全部楼层 |阅读模式
基本上只能实现单击,快速单击两下,只响应一次,使用的是下面这种键盘,每根线一端接地,直接连端口




代码如下
GPIO.H

  1. #ifndef __GPIO_H
  2. #define __GPIO_H

  3. #include "include.h"


  4. //板载LED灯
  5. #define OnBoardLedPort          GPIOC
  6. #define OnBoardLedPin                        GPIO_Pin_13

  7. //蜂鸣器
  8. #define BeepPort                                   GPIOC
  9. #define BeepPin                                                GPIO_Pin_15

  10. //OLED屏幕
  11. #define OLED1RCC                    RCC_APB2Periph_GPIOB
  12. #define OLED1Port                         GPIOB
  13. #define OLED1_SCL_Pin          GPIO_Pin_10
  14. #define OLED1_SDA_Pin          GPIO_Pin_11


  15. //按键
  16. #define KeyRCC    RCC_APB2Periph_GPIOA
  17. #define KeyPort   GPIOA
  18. #define K1Pin                        GPIO_Pin_0
  19. #define K2Pin                        GPIO_Pin_1
  20. #define K3Pin                        GPIO_Pin_2
  21. #define K4Pin                        GPIO_Pin_3
  22. #define K5Pin                        GPIO_Pin_4
  23. #define K6Pin                        GPIO_Pin_5
  24. #define K7Pin                        GPIO_Pin_6
  25. #define K8Pin                        GPIO_Pin_7


  26. #endif  //__GPIO_H

MAIN.H



  1. #include "include.h"


  2. #include "stm32f10x_gpio.h"
  3. #include "stm32f10x_exti.h"

  4. #include "delay.h"
  5. #include "sys.h"
  6. #include "oled.h"
  7. #include "bmp.h"
  8. #include "rocket.h"

  9. #include "gpio.h"

  10. #include "it.h"

  11. void NVIC_INIT(void);
  12. void GPIO_INIT(void);
  13. void SimpleBeep(void);

  14. //KEY* K1 = KeyMap(GPIOA,GPIO_Pin_8,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  15. //KEY* K2 = KeyMap(GPIOB,GPIO_Pin_12,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  16. //KEY* K3 = KeyMap(GPIOB,GPIO_Pin_13,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  17. //KEY* K4 = KeyMap(GPIOB,GPIO_Pin_14,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  18. //KEY* K5 = KeyMap(GPIOB,GPIO_Pin_15,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  19. //KEY* K6 = KeyMap(GPIOC,GPIO_Pin_13,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  20. //KEY* K7 = KeyMap(GPIOC,GPIO_Pin_14,GPIO_Mode_IPU,GPIO_Speed_50MHz);
  21. //KEY* K8 = KeyMap(GPIOC,GPIO_Pin_15,GPIO_Mode_IPU,GPIO_Speed_50MHz);

  22. int count = 0;

  23. int main(void)
  24. {
  25.                
  26.                 u8 t=' ';
  27.        
  28.                 NVIC_INIT();
  29.        
  30.                 GPIO_INIT();
  31.        
  32.                 delay_init();
  33.                 OLED_Init();
  34.                 OLED_ColorTurn(0);//0������ʾ��1 ��ɫ��ʾ
  35.                 OLED_DisplayTurn(0);//0������ʾ 1 ��Ļ��ת��ʾ
  36.                
  37.        
  38.                 GPIO_ResetBits(GPIOB,GPIO_Pin_12);
  39.        
  40.                 SimpleBeep();
  41.        
  42.                 while(1)
  43.                 {

  44.                 }

  45. }

  46. void GPIO_INIT(void)
  47. {
  48.                
  49.                 //打开端口
  50.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  51.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  52.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
  53.                
  54.        
  55.         //使用EXTI需要开AFIO(复用IO)
  56.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  57.        
  58.        
  59.                 //蜂鸣器PA1,送方波,遇低电平触发
  60.                 StdSetMode(BeepPort, BeepPin,GPIO_Mode_Out_PP,GPIO_Speed_2MHz,1);
  61.        
  62.                 //板载LED,PC13,LED接VCC,所以需要低电平触发
  63.                 StdSetMode(OnBoardLedPort, OnBoardLedPin,GPIO_Mode_Out_PP,GPIO_Speed_2MHz,1);
  64.        
  65.                
  66.                 //按键(上拉模式,置1)
  67.                 StdSetMode(KeyPort, K1Pin|K2Pin|K3Pin|K4Pin|K5Pin|K6Pin|K7Pin|K8Pin,GPIO_Mode_IPU,GPIO_Speed_10MHz,1);
  68.                
  69.                 //外部中断
  70.                 StdSetEXTI(GPIO_PortSourceGPIOA,GPIO_PinSource0,
  71.                                                                                 EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4 | EXTI_Line5 | EXTI_Line6 | EXTI_Line7,
  72.                                                                                 EXTI_Mode_Interrupt,EXTI_Trigger_Falling);
  73.                                                                                
  74.                                                                                
  75.                
  76. }

  77. void NVIC_INIT()
  78. {
  79.         StdSetNVIC(EXTI0_IRQn,0x0f,0x0f);
  80.         StdSetNVIC(EXTI1_IRQn,0x0f,0x0f);
  81.         StdSetNVIC(EXTI2_IRQn,0x0f,0x0f);
  82.         StdSetNVIC(EXTI3_IRQn,0x0f,0x0f);
  83.         StdSetNVIC(EXTI4_IRQn,0x0f,0x0f);
  84.         StdSetNVIC(EXTI9_5_IRQn,0x0f,0x0f);
  85. }






ROCKET.H


  1. #include "include.h"
  2. #include "stm32f10x_gpio.h"
  3. #include "stm32f10x_exti.h"



  4. #include "rocket.h"

  5. #include "delay.h"



  6. void StdSetMode(GPIO_TypeDef *      GPIOx ,
  7.                                                                 uint16_t                                                 Pin,               
  8.                                                                 GPIOMode_TypeDef                 mode,
  9.                                                                 GPIOSpeed_TypeDef         speed,
  10.                                                                 char                                                                set)
  11. {
  12.         GPIO_InitTypeDef  GPIO_InitStructure;
  13.        
  14.         GPIO_InitStructure.GPIO_Pin         = Pin;         
  15.         GPIO_InitStructure.GPIO_Mode         = mode;
  16.         GPIO_InitStructure.GPIO_Speed = speed;
  17.        
  18.         GPIO_Init(GPIOx, &GPIO_InitStructure);
  19.         if(set){
  20.                         GPIO_SetBits(GPIOx,Pin);
  21.         }else{
  22.                         GPIO_ResetBits(GPIOx,Pin);
  23.         }
  24.        
  25. }


  26. void StdSetEXTI(uint8_t GPIO_PortSourceGPIOx,
  27.                                                                 uint8_t GPIO_PinSourceN,
  28.                                                                 uint32_t EXTI_LineN,
  29.                                                                 EXTIMode_TypeDef  EXTI_Mode_Interrupt,    //中断或事件
  30.                                                                 EXTITrigger_TypeDef  EXTI_Trigger_Falling //上升沿或下降沿触发
  31. )
  32. {
  33.                 EXTI_InitTypeDef EXTIx;
  34.        
  35.                 GPIO_EXTILineConfig(GPIO_PortSourceGPIOx, GPIO_PinSourceN);

  36.                 EXTIx.EXTI_Line                 = EXTI_LineN;
  37.                 EXTIx.EXTI_Mode                 = EXTI_Mode_Interrupt;  
  38.                 EXTIx.EXTI_Trigger         = EXTI_Trigger_Falling;
  39.                 EXTIx.EXTI_LineCmd         = ENABLE;  
  40.                 EXTI_Init(&EXTIx);
  41.        
  42.        
  43. }



  44. void StdSetNVIC(uint8_t EXTIn_IRQn,uint8_t PPri,uint8_t SubPri)
  45. {
  46.         NVIC_InitTypeDef   NVICx;
  47.         NVICx.NVIC_IRQChannel = EXTIn_IRQn;
  48.         NVICx.NVIC_IRQChannelPreemptionPriority = PPri;
  49.         NVICx.NVIC_IRQChannelSubPriority = SubPri;
  50.         NVICx.NVIC_IRQChannelCmd = ENABLE;
  51.         NVIC_Init(&NVICx);
  52. }
  53. KEY* KeyMap(GPIO_TypeDef* GPIO,uint16_t Pin,GPIOMode_TypeDef Mode,GPIOSpeed_TypeDef Speed)
  54. {
  55.         KEY* k;
  56.         k->GPIO = GPIO;
  57.         k->Pin         = Pin;
  58.         k->Mode = Mode;
  59.         k->Speed = Speed;
  60.         return k;
  61. };

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

  3. #include "include.h"
  4. #include "stm32f10x_gpio.h"
  5. #include "stm32f10x_exti.h"
  6. #include "delay.h"
  7. #include "oled.h"
  8. #include "gpio.h"
  9. #include "rocket.h"

  10. extern int count;

  11. //K1中断
  12. void EXTI0_IRQHandler(void)
  13. {   
  14.        
  15.                 if(EXTI_GetITStatus(EXTI_Line0)!=RESET){
  16.                         delay_ms(50);
  17.                        
  18.                         if(GPIO_ReadInputDataBit(KeyPort,K1Pin)==0)
  19.                         {
  20.                                 count+=1;
  21.                                 OLED_ShowNum(1,1,count,3,16,1);
  22.                                 OLED_Refresh();
  23.                                 SimpleBeep();
  24.                                 GPIO_SetBits(KeyPort,K1Pin);
  25.                         }
  26.                         EXTI_ClearITPendingBit(EXTI_Line0);
  27.                        
  28.                 }
  29.                
  30. }

  31. void EXTI1_IRQHandler(void)
  32. {   
  33.        
  34.                 if(EXTI_GetITStatus(EXTI_Line1)!=RESET){
  35.                         delay_ms(50);
  36.                        
  37.                         if(GPIO_ReadInputDataBit(KeyPort,K2Pin)==0)
  38.                         {
  39.                                 count-=1;
  40.                                 OLED_ShowNum(1,1,count,3,16,1);
  41.                                 OLED_Refresh();
  42.                                 SimpleBeep();
  43.                                 GPIO_SetBits(KeyPort,K2Pin);
  44.                         }
  45.                         EXTI_ClearITPendingBit(EXTI_Line1);
  46.                 }
  47. }

  48. void EXTI2_IRQHandler(void)
  49. {   
  50.        
  51.                 if(EXTI_GetITStatus(EXTI_Line2)!=RESET){
  52.                         delay_ms(50);
  53.                        
  54.                         if(GPIO_ReadInputDataBit(KeyPort,K3Pin)==0)
  55.                         {
  56.                                 count+=1;
  57.                                 OLED_ShowNum(1,1,count,3,16,1);
  58.                                 OLED_Refresh();
  59.                                 SimpleBeep();
  60.                                 GPIO_SetBits(KeyPort,K3Pin);
  61.                         }
  62.                         EXTI_ClearITPendingBit(EXTI_Line2);
  63.                 }
  64. };

  65. void EXTI3_IRQHandler(void)
  66. {   
  67.        
  68.                 if(EXTI_GetITStatus(EXTI_Line3)!=RESET)
  69.                 {
  70.                         delay_ms(50);
  71.                        
  72.                         if(GPIO_ReadInputDataBit(KeyPort,K4Pin)==0)
  73.                         {
  74.                                 count+=1;
  75.                                 OLED_ShowNum(1,1,count,3,16,1);
  76.                                 OLED_Refresh();
  77.                                 SimpleBeep();
  78.                                 GPIO_SetBits(KeyPort,K4Pin);
  79.                         }
  80.                         EXTI_ClearITPendingBit(EXTI_Line3);
  81.                 }
  82. };

  83. void EXTI4_IRQHandler(void)
  84. {   
  85.        
  86.                 if(EXTI_GetITStatus(EXTI_Line4)!=RESET)
  87.                 {
  88.                         delay_ms(50);
  89.                        
  90.                         if(GPIO_ReadInputDataBit(KeyPort,K5Pin)==0)
  91.                         {
  92.                                 count+=1;
  93.                                 OLED_ShowNum(1,1,count,3,16,1);
  94.                                 OLED_Refresh();
  95.                                 SimpleBeep();
  96.                                 GPIO_SetBits(KeyPort,K5Pin);
  97.                         }
  98.                         EXTI_ClearITPendingBit(EXTI_Line4);
  99.                 }
  100. };
  101.                
  102. void EXTI9_5_IRQHandler(void)
  103. {   
  104.        
  105.                 if(EXTI_GetITStatus(EXTI_Line5)!=RESET)
  106.                 {
  107.                         delay_ms(50);
  108.                        
  109.                         if(GPIO_ReadInputDataBit(KeyPort,K6Pin)==0)
  110.                         {
  111.                                 count+=1;
  112.                                 OLED_ShowNum(1,1,count,3,16,1);
  113.                                 OLED_Refresh();
  114.                                 SimpleBeep();
  115.                                 GPIO_SetBits(KeyPort,K6Pin);
  116.                         }
  117.                         EXTI_ClearITPendingBit(EXTI_Line5);
  118.                 }
  119.                
  120.                 if(EXTI_GetITStatus(EXTI_Line6)!=RESET)
  121.                 {
  122.                         delay_ms(50);
  123.                        
  124.                         if(GPIO_ReadInputDataBit(KeyPort,K7Pin)==0)
  125.                         {
  126.                                 count+=1;
  127.                                 OLED_ShowNum(1,1,count,3,16,1);
  128.                                 OLED_Refresh();
  129.                                 SimpleBeep();
  130.                                 GPIO_SetBits(KeyPort,K7Pin);
  131.                         }
  132.                         EXTI_ClearITPendingBit(EXTI_Line6);
  133.                 }
  134.                
  135.                 if(EXTI_GetITStatus(EXTI_Line7)!=RESET)
  136.                 {
  137.                         delay_ms(50);
  138.                        
  139.                         if(GPIO_ReadInputDataBit(KeyPort,K8Pin)==0)
  140.                         {
  141.                                 count+=1;
  142.                                 OLED_ShowNum(1,1,count,3,16,1);
  143.                                 OLED_Refresh();
  144.                                 SimpleBeep();
  145.                                 GPIO_SetBits(KeyPort,K8Pin);
  146.                         }
  147.                         EXTI_ClearITPendingBit(EXTI_Line7);
  148.                 }
  149. };


  150. #endif  // __IT_H



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
lumia710 发表于 2021-2-17 11:04 | 显示全部楼层
看标题就知道是中断里做延时
nuaabob 发表于 2021-2-17 18:54 | 显示全部楼层
两次进入中断触发事件行不行?再加个定时器判断双击时间间隔?
gx_huang 发表于 2021-2-17 19:20 | 显示全部楼层
软件架构太差,在中断里有较长延时,你想让MCU自杀呀
gxs64 发表于 2021-2-17 22:11 | 显示全部楼层
中断的用法是:一般设置相应标志,尽快从中断中出来,在主程序中判标志。
ayb_ice 发表于 2021-2-18 08:30 | 显示全部楼层
我最反对按键用中断的,因为扫键根本花不了多少时间,资源,中断去抖还麻烦,如果做长,短,连按,这些还是需要算法来处理,典型的简单问题复杂化,还浪费中断这宝贵资源
wasonguo 发表于 2021-2-18 15:23 | 显示全部楼层
可否画个流程图?
sjnh 发表于 2021-2-18 15:27 | 显示全部楼层
本帖最后由 sjnh 于 2021-2-18 15:29 编辑

双击是你软件处理的事,退出中断做标志,并且有定时判断两次间隔,按键要做防抖处理
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

63

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部