由于网上购买的最小系统板子按键有限,自己加了一个按键在PA0上,单个按键需要实现多种功能,自己写了一个简单代码进行简单的单击、双击、三连击、长按等功能,以此简单记录。
编程思路:
如果只用标志位记录按键按下次数以此判断的话,无法准确做到在一定时间内判断是单击还是双击。在此我使用一个定时器进行记录按下按键在周期内是否有效。如果按键按下,开始进行计数,时间到后开始判断触发次数。
所以每当我按下按键,我就开启定时器3进行计时
按键的配置代码和中断如下:
void KEY_Init(void)
{
GPIO_InitTypeDef KEY_PIN;
EXTI_InitTypeDef KEY_exti;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
KEY_PIN.GPIO_Mode = GPIO_Mode_IPD; //上拉输入 GPIO
KEY_PIN.GPIO_Pin = GPIO_Pin_0; //选中0引脚
KEY_PIN.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&KEY_PIN); //初始化GPIO配置
KEY_exti.EXTI_Line = EXTI_Line0; //选中线0
KEY_exti.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
KEY_exti.EXTI_Trigger = EXTI_Trigger_Rising; //下降沿触发
KEY_exti.EXTI_LineCmd = ENABLE; //使能中断请求
EXTI_Init(&KEY_exti); //初始化结构体
NVIC_EnableIRQ(EXTI0_IRQn); //开启exti0中断编号进行工作,默认自然优先级
}
u8 KEY_CONR; //记得全局声明这个变量
void EXTI0_IRQHandler(void)
{
delay_ms(100);
//清除中断标志位
EXTI_ClearITPendingBit(EXTI_Line0);
TIM_Cmd( TIM3,ENABLE);//按下按键开始计时,时间到进入定时器中断
KEY_CONR++;//按下按键累计次数
}
我这里使用的是通用定时器3进行一个基本定时,代码如下:
void TIM3_Init(u16 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3时钟
//初始化TIM3
TIM_TimeBaseInitStructure.TIM_Period=5000-1; //自动装载值5000
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1; //分频系数7200
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不分频
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除标志
TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE); //使能定时器溢出更新中断
NVIC_EnableIRQ(TIM3_IRQn); //使能TIM3_IRQn中断编号进行工作,默认自然优先级编号
//TIM_Cmd(TIM3,ENABLE); //使能定时器
}
定时器3的中断服务函数进行标志位判定,代码如下:
void TIM3_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除标志
if(KEY0==0&&KEY_CONR==2)//按下按键松手,并且超过1秒只触发两次按键中断
{
KEY_CONR=0;//清空标志,下次还能触发
TIM_Cmd( TIM3,DISABLE);//判断单双击
printf("触发双击!\r\n");
LED0=0;
}
else if(KEY0==0&&KEY_CONR==1)//按下按键松手,并且超过1秒只触发一次按键中断
{
KEY_CONR=0;//清空标志,下次还能触发
TIM_Cmd( TIM3,DISABLE);
printf("触发单击\r\n");
LED0=1;
}else if(KEY_CONR>=3)//三连击,我这里不需要
{
KEY_CONR=0;//清空标志,下次还能触发
TIM_Cmd( TIM3,DISABLE);
printf("此次按键功能不存在\r\n");
}else if(KEY0==1&&KEY_CONR==1)//按下按键没有松手,并且超过1秒只触发一次按键中断,这里存在小BUG,必须要按够1秒不松手才算触发
{
KEY_CONR=0;//清空标志,下次还能触发
TIM_Cmd( TIM3,DISABLE);
printf("触发长按\r\n");
}
}
注:因为板子只有一个按键,还有剩余的定时器可以使用,如果定时器不够的话,不建议这么去占用宝贵的定时器。