学习目标:
1. 按键单击
2. 按键双击
3. 按键长按
实验思路:
使用定时器来完成对按键长按,单击,双击的检测。
实验代码:
//定时器采用的定时器7周期周期为30ms
#define Press_Time 60 //长按时间 1.8s
#define KEY_Response_Time 10 //按键响应时间 300ms
enum{
Click = 0x01,//单机标志
Double_Click = 0x02,//双击标志
Press = 0x04 //长按2s标志
};
typedef struct {
uint8_t volatile KEY_Count;//按下时间计数
uint8_t KEY_Flag;//按键标志
}User_Key_t;
User_Key_t KEY0={0,0};
User_Key_t KEY1={0,0};
User_Key_t KEY2={0,0};
User_Key_t WKUP={0,0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint8_t tim300_count;
static uint8_t count_flag;
if(htim == &htim7) //确定是定时器6产生的中断
{
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==RESET){
KEY0.KEY_Count++;
}
else if(KEY0.KEY_Count){
if(KEY0.KEY_Count>Press_Time){KEY0.KEY_Flag=Press;KEY0.KEY_Count=0;count_flag=0;tim300_count=0;return;}
if(count_flag==0){KEY0.KEY_Count=0;count_flag=0X01;}
}
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==RESET){
KEY1.KEY_Count++;
}else if(KEY1.KEY_Count){
if(KEY1.KEY_Count>Press_Time){KEY1.KEY_Flag=Press;KEY1.KEY_Count=0;count_flag=0;tim300_count=0;return;}
if(count_flag==0){KEY1.KEY_Count=0;count_flag=0X02;}
}
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==RESET){
KEY2.KEY_Count++;
}else if(KEY2.KEY_Count){
if(KEY2.KEY_Count>Press_Time){KEY2.KEY_Flag=Press;KEY2.KEY_Count=0;count_flag=0;tim300_count=0;return;}
if(count_flag==0){KEY2.KEY_Count=0;count_flag=0X04;}
}
if(HAL_GPIO_ReadPin(WKUP_GPIO_Port,WKUP_Pin)==SET){
WKUP.KEY_Count++;
}else if(WKUP.KEY_Count){
if(WKUP.KEY_Count>Press_Time){WKUP.KEY_Flag=Press;WKUP.KEY_Count=0;count_flag=0;tim300_count=0;return;}
if(count_flag==0){WKUP.KEY_Count=0;count_flag=0X08;}
}
if(count_flag){
tim300_count++;
}
if(tim300_count>=KEY_Response_Time){
if(KEY0.KEY_Count>2){KEY0.KEY_Flag=Double_Click;KEY0.KEY_Count=0;tim300_count=0;count_flag=0;return;}//双击
else if(KEY1.KEY_Count>2){KEY1.KEY_Flag=Double_Click;KEY1.KEY_Count=0;tim300_count=0;count_flag=0;return;}//双击
else if(KEY2.KEY_Count>2){KEY2.KEY_Flag=Double_Click;KEY2.KEY_Count=0;tim300_count=0;count_flag=0;return;}//双击
else if(WKUP.KEY_Count>2){WKUP.KEY_Flag=Double_Click;WKUP.KEY_Count=0;tim300_count=0;count_flag=0;return;}//双击
if(count_flag==0x01) {KEY0.KEY_Flag=Click;tim300_count=0;count_flag=0;return;}//单击
else if(count_flag==0x02) {KEY1.KEY_Flag=Click;tim300_count=0;count_flag=0;return;}//单击
else if(count_flag==0x04){KEY2.KEY_Flag=Click;tim300_count=0;count_flag=0;return;}//单击
else if(count_flag==0x08){WKUP.KEY_Flag=Click;tim300_count=0;count_flag=0;return;}//单击
}
}
}
主函数里调用
switch(KEY0.KEY_Flag)
{
case Click:
printf("%d\r\n",KEY0.KEY_Flag);
LED.LED_On(LED1_GPIO_Port,LED1_Pin);
LED.LED_Off(LED0_GPIO_Port,LED0_Pin);
KEY0.KEY_Flag=0x00;
break;
case Double_Click:
printf("%d\r\n",KEY0.KEY_Flag);
LED.LED_Off(LED1_GPIO_Port,LED1_Pin);
LED.LED_On(LED0_GPIO_Port,LED0_Pin);
KEY0.KEY_Flag=0x00;
break;
case Press:
printf("%d\r\n",KEY0.KEY_Flag);
LED.LED_Off(LED1_GPIO_Port,LED1_Pin);
LED.LED_Off(LED0_GPIO_Port,LED0_Pin);
KEY0.KEY_Flag=0x00;
break;
}