前言:
本文使用cubemx软件,利用定时器10ms中断实现按键的长按、短按、双击。
定时器通常是通过一个晶体振荡器和一个计数器实现的。晶体振荡器可以产生稳定的时间基准,计数器可以根据振荡器提供的稳定时钟信号进行计数。当计数达到预设的值时,计数器就会触发一个中断信号。通过调整计数器的预设值和时钟信号的频率,我们就可以实现不同时间间隔的定时器。
例如,我们的频率为80MHz,我们可以将分频系数设置为80-1,重装载值设置为10000-1,则中断时间为80000000/80/10000=100HZ,1/100=0.01秒,即10ms。
定时器10ms进入一次中断,回调函数中读取引脚电平状态,由于按键抖动不会超过10ms,通过多次引脚电平保持时长进行判断,可实现短按、长按、双击。
CUBEMX配置如下:
时钟树配置:
定时器配置(蓝桥杯选手建议使用TIM6):
记得开启NVIC:
引脚配置为输入状态即可。
代码如下:
开启定时器中断代码如下:
HAL_TIM_Base_Start_IT(&htim6);
中断回调函数如下:
struct keystruct {
uint8_t keyLevel;
uint8_t keyShort;
uint8_t keyLong;
uint8_t KeyDouble;
uint8_t keyTime1;
uint8_t keyTime2;
uint8_t keyChoose;
}key[4];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
key[0].keyLevel=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].keyLevel=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].keyLevel=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].keyLevel=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(key[i].keyChoose)
{
case 0:
if(key[i].keyLevel==0)
key[i].keyChoose=1; //按下
break;
case 1:
if(key[i].keyLevel==0)
key[i].keyChoose=2; //消抖
else
key[i].keyChoose=0; //去抖
break;
case 2:
if(key[i].keyLevel==0) //单击计时
key[i].keyTime1++;
else
key[i].keyChoose=3; //已松手
break;
case 3:
if(key[i].keyLevel==1)
{
key[i].keyTime2++; //等待双击开始计时
if(key[i].keyTime2>30) // 等待时间过长,长按短按判断
{
if(key[i].keyTime1<70)
key[i].keyShort=1; //是短按
else
key[i].keyLong=1; //长按
key[i].keyChoose=0; //清除标志
key[i].keyTime1=0;
key[i].keyTime2=0;
}
}
else
key[i].keyChoose=4; //双击开始
break;
case 4:
if(key[i].keyLevel==0) //不是消抖
key[i].keyChoose=5;
else //是抖动
{
if(key[i].keyTime1<70)
key[i].keyShort=1; //是短按
else
key[i].keyLong=1; //长按
key[i].keyChoose=0;
key[i].keyTime1=0;
key[i].keyTime2=0;
}
break;
case 5:
if(key[i].keyLevel==1) //双击松手
{
key[i].KeyDouble=1;
key[i].keyChoose=0;
key[i].keyTime1=0;
key[i].keyTime2=0;
}
break;
}
}
}
屏幕显示代码如下:
void keyProc(void)
{
char chPorc[21];
for(int i=0;i<4;i++)
{
if(key[i].keyShort==1)
{
key[i].keyShort=0;
sprintf(chPorc,(const char *)"KEY SHORT = %d ",i+1);
LCD_DisplayStringLine(Line2,(u8 *)chPorc);
}
if(key[i].keyLong==1)
{
key[i].keyLong=0;
sprintf(chPorc,(const char *)"KEY LONG = %d ",i+1);
LCD_DisplayStringLine(Line2,(u8 *)chPorc);
}
if(key[i].KeyDouble==1)
{
key[i].KeyDouble=0;
sprintf(chPorc,(const char *)"KEY DOUBLE = %d ",i+1);
LCD_DisplayStringLine(Line2,(u8 *)chPorc);
}
}
}
最后
mian函数中调用一下即可
链接
链接:https://pan.baidu.com/s/1-tUgoAmMSVSJ0tivBjPNJQ?pwd=la74
提取码:la74