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 ++;//多击按键次数+1Fcnt = 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;}
}