基本每届必考(长按、短按、双击)
原理: 1、判断引脚高低电平,按下接GND,引脚为0,反之。
2、使用定时器中断,每隔一段时间扫描引脚电平,做判断。
一、cubemx
配置gpio
PB0/1/2和PA0->GPIO_inout
gpio->gpio pull-up(上拉)
配置定时器(通用可选tim2\3\4)
tim3->clock source->internal clock(内部时钟 前文80mhz)
prescaler(预分频)->80-1 (80000000/80=1000000(决定工作频率))
counter period /arr(重装载值)->10000-1 (1000000/10000=100hz(10ms中断一次->扫描一次按键))
nvic settings->enabled√(使能nvic)
二、keil
创建新文件interrupt.c/.h
//interrupt.c
#include "interrupt.h" // Device header
struct keys key[4]={0,0,0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
//该中断回调函数可在函数库xxxxhal_tim.h 复制
{
if(htim->Instance==TIM3)
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=1;
}
}
break;
case 1://消抖
{
if(key[i].key_sta==0)
{
key[i].judge_sta=2;
key[i].single_flag=1;
}
else
{
key[i].judge_sta=0;
}
}
break;
case 2://松手
{
if(key[i].key_sta==1)
{
key[i].judge_sta=0;
}
}
break;
}
}
}
}
//interrupt.h
#ifndef __INTERRUPT_H_
#define __INTERRUPT_H_
#include "main.h"
#include "stdbool.h"
struct keys
{
uchar judge_sta; //判断进行到哪一步
bool key_sta; //01两种状态,是否被按下,按下为0
bool single_flag; //按下转为1
};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
#endif
回到main.c 添加
#include "interrupt.h"
/* Private typedef ----*/
/* USER CODE BEGIN PTD */
extern struct keys key[];
/* USER CODE END PTD */
HAL_TIM_Base_Start_IT(&htim3); (打开tim3)
while(1)
{
if(key[0].single_flag==1)
{
sprintf(text," key0 down ");
LCD_DisplayStringLine(Line8, (unsigned char *)text);
key[0].single_flag=0;
}
if(key[1].single_flag==1)
{
sprintf(text," key1 down ");
LCD_DisplayStringLine(Line8, (unsigned char *)text);
key[1].single_flag=0;
}
}
参考手册p76