
配置成上拉模式

开启tim4的定时器和中断,配置成10ms方便消抖

开启中断

配置完成
代码部分:
单击:
key.c
#include "key.h"
struct keys key[4] = {0,0,0};
uchar i;
uchar time_flag;
uint time_count;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM4)
{
key[0].key_flag = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_flag = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_flag = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_flag = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(i=0;i<4;i++)
{
switch (key[i].key_count)
{
case 0:
if(key[i].key_flag == 0)
{
key[i].key_count = 1;
}
break;
case 1:
if(key[i].key_flag == 0)
{
key[i].key_count = 2;
}
else
{
key[i].key_count = 0;
}
break;
case 2:
if(key[i].key_flag == 1)
{
key[i].key_count = 0;
key[i].key_zhi = 1;
}
break;
}
}
if(time_flag == 1)
{
time_count++;
}
}
}
key.h
#ifndef _KEY_H_
#define _KEY_H_
#include "main.h"
#include "stdbool.h"
struct keys
{
uchar key_count;
bool key_flag;
bool key_zhi;
};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
#endif
main.c
extern struct keys key[]; //声明结构体
HAL_TIM_Base_Start_IT(&htim4); //初始化开启定时器
key_porc函数:
void key_porc(void)
{
if(key[0].key_zhi == 1) //B1
{
key[0].key_zhi = 0;
}
if(key[1].key_zhi == 1) //B2
{
key[1].key_zhi = 0;
}
if(key[2].key_zhi == 1) //B3
{
key[2].key_zhi = 0;
}
if(key[3].key_zhi == 1) //B4
{
key[3].key_zhi = 0;
}
}
单击+长按
key.c
#include "key.h"
struct keys key[4]={0,0,0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
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;
key[i].key_time=0;
}
}
break;
case 1:
{
if(key[i].key_sta==0)
{
key[i].judge_sta=2;
}
else key[i].judge_sta=0;
}
break;
case 2:
{
if(key[i].key_sta==1)
{
key[i].judge_sta=0;
if(key[i].key_time<70)
{
key[i].single_flag=1;
}
}
else
{
key[i].key_time++;
if(key[i].key_time>70) key[i].long_flag=1;
}
}
break;
}
}
}
}
key.h
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include "main.h"
#include "stdbool.h"
void HAL_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
struct keys
{
uchar judge_sta;
bool key_sta;
bool single_flag;
bool long_flag;
uint key_time;
};
#endif
单击+长按+双击
key.c
#include "key.h"
uchar judge_state[4]={0},double_click_time[4]={0},key_state[4]={0},double_click_timerEN[4]={0},
single_key_flag[4]={100},double_key_flag[4]={0},long_key_flag[4]={0};
uint key_time[4]={0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//回调函数
{
if(htim->Instance==TIM3)//定时器3的事件
{
key_state[0]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key_state[1]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key_state[2]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key_state[3]=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch (judge_state[i])
{
case 0:
{
if(key_state[i]==0)//按键按下
{
judge_state[i]=1;
key_time[i]=0;
}
break;
}
case 1://消抖过程
{
if(key_state[i]==0)
{
judge_state[i]=2;
}
else judge_state[i]=0;//未按下
break;
}
case 2:
{
if((key_state[i]==1)&&key_time[i]<70)//等待松开过程,且非长按键
{
if(double_click_timerEN[i]==0) //可能双击按键的第一次,进入计时
{
double_click_timerEN[i]=1;
double_click_time[i]=0;
}
else //在计时范围内又按了一次
{
double_key_flag[i]=1;//双击情况
double_click_timerEN[i]=0;
}
judge_state[i]=0;
}
else if(key_state[i]==1&&key_time[i]>=70) judge_state[i]=0;//松开且是长按键
else
{
if (key_time[i]>=70)long_key_flag[i]=1;//长按键
key_time[i]++;//长按键计时?还没松开
}
break;
}
}
if(double_click_timerEN[i]==1)//延时确认是否双击
{
double_click_time[i]++;
if(double_click_time[i]>=35)
{
single_key_flag[i]=1;//按键1单次按下
double_click_timerEN[i]=0;
}
}
}
}
}
main.c
extern uchar single_key_flag[4],long_key_flag[4],double_key_flag[4];
key.h
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include "main.h"
#include "stdbool.h"
void HAL_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
struct keys
{
uchar judge_sta;
bool key_sta;
bool single_flag;
bool long_flag;
uint key_time;
};
#endif
key_porc函数
if(single_key_flag[0]==1)//1被单次按下
{
single_key_flag[0]=0;//用完标记
}
if(long_key_flag[0]==1)//700ms长按键
{
long_key_flag[0]=0;
}
if(double_key_flag[0]==1)//双击判断
{
double_key_flag[0]=0;
}
if(single_key_flag[1]==1)//2被单次按下
{
single_key_flag[1]=0;//用完标记
}
if(long_key_flag[1]==1)//700ms长按键
{
long_key_flag[1]=0;
}
if(double_key_flag[1]==1)//双击判断
{
double_key_flag[1]=0;
}
if(single_key_flag[2]==1)//3被单次按下
{
single_key_flag[2]=0;//用完标记
}
if(long_key_flag[2]==1)//700ms长按键
{
long_key_flag[2]=0;
}
if(double_key_flag[2]==1)//双击判断
{
double_key_flag[2]=0;
}
if(single_key_flag[3]==1)//4被单次按下
{
single_key_flag[3]=0;//用完标记
}
if(long_key_flag[3]==1)//700ms长按键
{
long_key_flag[3]=0;
}
if(double_key_flag[3]==1)//双击判断
{
double_key_flag[3]=0;
}
以上就是蓝桥杯嵌入式按键的所有内容。