CUBE里将这几个引脚配置成GPIO输入模式,再同时选中,配置成上拉,如下图:
同时配置定时器,定时10ms,每10ms扫描一次按键,计算公式:80 000 000 / 80 / 10000 = 100HZ = 10ms,配置如下图(记得使能中断):
中断文件:
interrupt.c
#include "interrupt.h"
extern uint8_t flag_10ms;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
flag_10ms = 1;
}
}
interrupt.h
#ifndef __interrupt_h
#define __interrupt_h
#include "main.h"
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
#endif
在主函数里打开定时器2中断:
HAL_TIM_Base_Start_IT(&htim2 );
按键文件:
key.c
按键原理:
以代码中的B1为例:每10ms进来一次按键,哪个按键按下对应的t就+1,当松手后就判断t值,大于100(1s)即为长按,大于2小于100(20ms < t < 1000ms)即为短按。
以B2为例:在短按的时候设置一个时间,这里我设置的是500ms,500ms内如果有按键按下,就重置Fcnt = 50,同时Key_cnt + 1;若没有,则当500ms过去后,就判断Key_cnt的值,从而知道多击的次数。在最后,要将Key_cnt,Fcnt清零。
至于组合键,很简单,也感觉不会考。。。。。
#include "key.h"
uint8_t flag_10ms;
uint8_t Key_Scan(void)
{
uint8_t key_temp = 0;
static uint8_t t1 = 0;
static uint8_t t2 = 0;
static uint8_t Fcnt = 0;//多击按键计时
static uint8_t Key_cnt = 0;//记录按键多击次数
if(flag_10ms == 1)
{
if(B1 == 0) t1++;
if(B1 == 1)
{
if(t1 > 100) //长按
{
key_temp = 10;
}
else if(t1 > 2)//短按(20ms)
{
key_temp = 1;
}
t1 = 0;
}
if(B2 == 0) t2++;
if(B2 == 1)
{
if(t2 > 100)
{
key_temp = 20;
}
else if(t2 > 2)
{
Key_cnt ++;//多击按键次数+1
Fcnt = 50;//计时500Ms
}
t2 = 0;
if(Fcnt)
{
Fcnt--;
if(Fcnt == 0)//当没有按键按下时
{
if(Key_cnt == 1)//单击
{
key_temp = 2;
}
else if(Key_cnt == 2)//双击
{
key_temp = 22;
}
Key_cnt = 0;
Fcnt = 0;
}
}
}
if(B3 == 0)
{
if(B4 == 0) //组合键
{
key_temp = 34;
}
}
flag_10ms = 0;
}
return key_temp;
}
key.h
#ifndef __key_h
#define __key_h
#include "main.h"
#define B1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define B2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define B3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define B4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
uint8_t Key_Scan(void);
#endif
main.h
按键处理函数,本例实现按键点灯的功能,如下:
void Key_Pro(void)
{
switch(Key_Scan())
{
case 1://B1短按
Led_disp(0);
break;
case 10://B1长按
Led_disp(1);
break;
case 2://B2短按
Led_disp(2);
break;
case 20://B2长按
Led_disp(3);
break;
case 22://B2双击
Led_disp(4);
break;
}
}