对于cubemx的配置
打开一个定时器,打开对应的按键中断即可。
代码
KeyMode.h
#ifndef __KEY_MODE_H_
#define __KEY_MODE_H_
#include "stdint.h"
#define KeyTim htim7
#define KeyMode TIM7
#endif /*__KEY_MODE_H_*/
KeyMode.c
#include "tim.h"
#include "gpio.h"
#include "KeyMode.h"
/*handle end*/
/*Private variables start*/
//bit0~3是按键PA0 的标志位
//bit4~7是按键PC13的标志位
//第0 位是按键第一次按下的标志位
//第1 位是按键第二次按下的标志位
//第2 位是按键第二次按下的标志位
//第3 位是按键第二次按下的标志位
static uint8_t KeyMode_Flag=0;
/*Private variables end*/
void singleClick_Key1Fun(void); //按键1单击处理函数
void singleClick_Key2Fun(void); //按键2单击处理函数
void doubleClick_Key1Fun(void); //按键1双击处理函数
void doubleClick_Key2Fun(void); //按键2双击处理函数
void longTerm_Key1Fun(void); //按键1长时间按下处理函数
void longTerm_Key2Fun(void); //按键2长时间按下处理函数
void yxy_delay_us(uint32_t us)
{
SysTick->CTRL =0;
SysTick->LOAD =72*us-1;
SysTick->VAL =0;
SysTick->CTRL =5;
while((SysTick->CTRL & 0x10000) == 0);
SysTick->CTRL =0;
}
void yxy_delay_ms(uint32_t ms)
{
while(ms--)
{
SysTick->CTRL =0;
SysTick->LOAD =72000-1;
SysTick->VAL =0;
SysTick->CTRL =5;
while((SysTick->CTRL & 0x10000) == 0);
}
SysTick->CTRL =0;
}
/*单击*/
void singleClick_Key1Fun(void)
{
}
/*双击*/
void doubleClick_Key1Fun(void)
{
}
/*三击*/
void threeClick_Key1Fun(void)
{
}
/*四击*/
void fourClick_Key1Fun(void)
{
}
/*长按*/
void longTerm_Key1Fun(void)
{
}
/* 流程
按键先按下,在300ms内没有第二次按下就代表是单击,
一但在300ms以内按下第二次就代表是双击,
当按键一直未松手,超过1500ms时就是长按。
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
printf("EX\r\n");
if(GPIO_Pin == GPIO_PIN_0) //PA0
{
if((KeyMode_Flag&0x08) == 0x08) //判断按键1在之前是否按下3次
{
KeyMode_Flag |= 0x08;//代表第四次按下了
}
if((KeyMode_Flag&0x02) == 0x02) //判断按键1在之前是否按下2次
{
KeyMode_Flag |= 0x04;//代表第三次按下了
}
if((KeyMode_Flag&0x01) == 0x01) //判断按键1在之前是否按下
{
KeyMode_Flag |= 0x02;//代表第二次按下了
}
KeyMode_Flag |= 0x01; //按键1按下标志位置位
// 计数器值清零,,从当前开始计数,也充当了短暂的按键消抖的作用
__HAL_TIM_SET_COUNTER(&KeyTim, 0);
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //TIM7
{
static uint8_t Key1_Cnt30 = 0;//判断单击还是双击的变量
uint8_t long_termK1=0; //判断长按的还是其他的变量
if(htim->Instance == KeyMode) //来只定时器6的溢出中断
{
if((KeyMode_Flag&0x01) == 0x01) //按键1按下计时
{
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) //这里代表按键还未松开(对于野火来说按下时是高电平)
{
if(((KeyMode_Flag&0x02) == 0x02) || ((KeyMode_Flag&0x04) == 0x04) || ((KeyMode_Flag&0x08) == 0x08))//当确认是第二次以上按下的时候,直接跳出长时间按下处理函数
{
break;
}
yxy_delay_ms(10);//计时
long_termK1++;
if(long_termK1>=100) // 10ms*100 == 1000ms
{
long_termK1=0;
KeyMode_Flag = 0; //清空标志位
longTerm_Key1Fun();//处理长时间按下的函数
break;
}
}
Key1_Cnt30++;
if(Key1_Cnt30>=50 && (KeyMode_Flag&0x08) == 0x08)//四击
{
fourClick_Key1Fun();//四击处理函数
Key1_Cnt30=0;
KeyMode_Flag = 0;//清空标志位
}
if(Key1_Cnt30>=40 && (KeyMode_Flag&0x08) != 0x08)//三击
{
threeClick_Key1Fun();//三击处理函数
Key1_Cnt30=0;
KeyMode_Flag = 0;//清空标志位
}
if(Key1_Cnt30>=30 && (KeyMode_Flag&0x04) != 0x04)
{
if((KeyMode_Flag&0x02) == 0x02)//代表在一定的时间内,连续按下两次了,说明是双击
{
doubleClick_Key1Fun();//双击处理函数
}
else //说明是单击
{
singleClick_Key1Fun();//单击处理函数
}
Key1_Cnt30=0;
KeyMode_Flag = 0;//清空标志位
}
}
}
}
使用
只要更改KeyMode.c的这些回调函数,里面的内容就可以实现功能
/*单击*/
void singleClick_Key1Fun(void)
{
}
/*双击*/
void doubleClick_Key1Fun(void)
{
}
/*三击*/
void threeClick_Key1Fun(void)
{
}
/*四击*/
void fourClick_Key1Fun(void)
{
}
/*长按*/
void longTerm_Key1Fun(void)
{
}