邏輯是通過定時器溢出周期進行判斷按下次數
比如設置定時器溢出周期為500MS,每次溢出都會判斷按鍵按下次數,如果下個周期前沒有觸發按下,則結束鍵值判斷.并確定觸發鍵值.清空按下次數標志.測試比一個定時器周期按下按鍵次數判斷寫法要穩定...
記錄STM32實現多功能按鍵_stm32一個按鍵實現多種功能-CSDN博客
直接上代碼,這里使用的是M4內核芯片,如果需要使用M3則修改初始化代碼
按鍵外部中斷代碼
#include "exti.h"
#include "key.h"
#include "systick.h"
#include "TIM6.h"#include "io_bit.h" //位帶操作 正點原子的是SYS.H
#define KEY1 PAin(0) extern u8 multi_flag; //外部聲明//PA0---KEY1
void Exti_Init(void)//函數定義
{EXTI_InitTypeDef EXTI_KEY_Init={0};NVIC_InitTypeDef NVIC_KEY_Init={0};//1.配置SYSCFG系統配置寄存器時鐘使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//2.打開GPIOABC外設時鐘使能 RCC->AHB1ENRRCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//KEY1GPIO_InitTypeDef GPIO_KEY_Init={0};GPIO_KEY_Init.GPIO_Mode=GPIO_Mode_IN;GPIO_KEY_Init.GPIO_Pin=GPIO_Pin_0;GPIO_KEY_Init.GPIO_PuPd=GPIO_PuPd_DOWN;GPIO_Init(GPIOA, &GPIO_KEY_Init);//3.映射對應的中斷線到IO上SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);//4.配置EXTI中斷初始化EXTI_KEY_Init.EXTI_Line=EXTI_Line0;//中斷線EXTI_KEY_Init.EXTI_LineCmd=ENABLE;EXTI_KEY_Init.EXTI_Mode=EXTI_Mode_Interrupt;//中斷模式EXTI_KEY_Init.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿觸發EXTI_Init(&EXTI_KEY_Init);//5.配置NVIC中斷控制器初始化NVIC_KEY_Init.NVIC_IRQChannel=EXTI0_IRQn;NVIC_KEY_Init.NVIC_IRQChannelCmd=ENABLE;NVIC_KEY_Init.NVIC_IRQChannelPreemptionPriority=2;NVIC_KEY_Init.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_KEY_Init);
}
//6.配置中斷服務函數
u8 multi_flag;//記錄按下的次數 需要外部聲明
void EXTI0_IRQHandler(void)
{int i=20;delay(1500);if(EXTI_GetITStatus(EXTI_Line0)){ TIM_Cmd(TIM6, ENABLE);printf("KEY1外部中斷觸發,打開定時器\r\n");multi_flag++;//記錄按下次數TIM_SetCounter(TIM6,0);//更新計數}//7.清除中斷標志 EXTI_ClearITPendingBit(EXTI_Line0);
}
定時器配置:
#include "TIM6.h"
#include "exti.h"void Tim6_Init(uint32_t prc,uint32_t arr)
{//定義結構體變量TIM_TimeBaseInitTypeDef TIM_Time6_Init={};NVIC_InitTypeDef NVIC_Time6_Init={};//對定時器TIM6時鐘使能 RCC_APB1ENRRCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM6,ENABLE);//給成員賦值TIM_Time6_Init.TIM_ClockDivision=TIM_CKD_DIV1;//不分頻TIM_Time6_Init.TIM_CounterMode=TIM_CounterMode_Up;//TIM6只有向上計數TIM_Time6_Init.TIM_Period=arr;//重裝載TIM_Time6_Init.TIM_Prescaler=prc-1;//xxx+1 預分頻//定時器TIM_Init()初始化函數調用TIM_TimeBaseInit(TIM6, &TIM_Time6_Init);//使能定時器TIM_Cmd(TIM6, DISABLE);//打開定時器中斷TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);//清除定時器中斷標志位TIM_ClearITPendingBit( TIM6,TIM_IT_Update);//NVIC優先級配置 NVIC_Time6_Init.NVIC_IRQChannel=TIM6_DAC_IRQn;//中斷源NVIC_Time6_Init.NVIC_IRQChannelCmd=ENABLE;//使能中斷NVIC_Time6_Init.NVIC_IRQChannelPreemptionPriority=2;//搶占優先級NVIC_Time6_Init.NVIC_IRQChannelSubPriority=2;//響應優先級 NVIC_Init(&NVIC_Time6_Init);
}
//編寫中斷服務函數(1s時間進一次中斷)
void TIM6_DAC_IRQHandler(void)
{if(TIM_GetITStatus(TIM6,TIM_IT_Update)){TIM_Cmd(TIM6, DISABLE);printf("TIM6定時時間到!\r\n");if(KEY1==0&&multi_flag==1)//松手并且標志位為1---單擊 KEY1 位帶操作{printf("觸發單擊!\r\n");}else if(KEY1==0&&multi_flag==2)// KEY1 位帶操作{printf("觸發雙擊!\r\n");}else if(KEY1==0&&multi_flag==3){printf("觸發三擊!\r\n");}else if(KEY1==0&&multi_flag>3){printf("此功能不存在\r\n");}else if(KEY1==1&&multi_flag==1){printf("長按\r\n");}multi_flag=0;//清空標志}//清除中斷標志位TIM_ClearITPendingBit( TIM6,TIM_IT_Update);
}