主控芯片:GD32F303CBT6
1、按键扫描结构体
首先定义一个结构体
typedef struct
{
u32 gpio_periph;
u32 pin;
u8 Last_Status; //上个工作模式
u8 Key_Status; //工作模式
u8 Key_Down_OK; //按下
u8 Key_Long_Up; //松开
u8 Key_Single_Up; //松开过
u8 Key_Press_Type; //按键类型,短按、长按
u8 Key_Single_Cnt; //连续单击计数
u16 Key_Single_TimeSet; //短按时间阈值
u16 Key_Long_TimeSet; //长按时间阈值
u16 Key_SP_Long_TimeSet;//更长时间阈值
u16 Key_SP2_Long_TimeSet;//更长时间阈值
u32 KFilter; //按下计数
u32 UP_KFilter; //松开计数
}Button_Scan_Class;
extern Button_Scan_Class IOT_Switch; //按键
2、按键初始化
void Button_Scan_Init_Config(void)
{
memset(&IOT_Switch, 0 ,sizeof(IOT_Switch));
//按键时间阈值设定 IOT
IOT_Switch.Key_Single_TimeSet = KEY_50MS_TIME_SET;
IOT_Switch.Key_Long_TimeSet = KEY_2S_TIME_SET;
IOT_Switch.Key_SP_Long_TimeSet = KEY_5S_TIME_SET;
IOT_Switch.Key_Status = Standby_status;
//按键引脚定义
IOT_Switch.gpio_periph = KEY_GPIO;
IOT_Switch.pin = KEY_GPIO_PIN;
rcu_periph_clock_enable(RCU_GPIOB);
gpio_init(KEY_GPIO, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, KEY_GPIO_PIN); //RESET
}
按键设定的阈值时间,由自己定义需要多长。这里定义为短按50毫秒,长按2秒,长按5秒。
3、按键扫描函数
void Button_Scan_State(Button_Scan_Class* Str_Key, u8* beep_status)
{
if(RESET==gpio_input_bit_get(Str_Key->gpio_periph,Str_Key->pin)) //判断是否按下
{
if(Str_Key->Key_Single_Up ==1)
{
Str_Key->Key_Single_Up =0;
Str_Key->KFilter=0;
}
if(Str_Key->KFilter++>2 && Str_Key->UP_KFilter >= 3) //按下开始计数
{
Str_Key->Key_Down_OK = 1; // 按键按下标志位
Str_Key->UP_KFilter = 0;
}
//Str_Key->Key_Long_Up = 0;
}
else if(Str_Key->Key_Down_OK == 1) //确认按下按键
{
Str_Key->Key_Single_Up =1;
if(Str_Key->UP_KFilter == 0) Str_Key->Key_Single_Cnt++;
if(Str_Key->UP_KFilter < 50) Str_Key->UP_KFilter++;
else Str_Key->Key_Long_Up = 1;
}
else
{
Str_Key->KFilter = 0;
if(Str_Key->UP_KFilter < 50) Str_Key->UP_KFilter++;
}
if(Str_Key->Key_Long_Up==1)
{
if(Str_Key->KFilter > Str_Key->Key_SP_Long_TimeSet)//5S长按
{
Str_Key->Key_Press_Type = KEY_SP_LONG_MODE;
}
else if(Str_Key->KFilter > Str_Key->Key_Long_TimeSet) //2S长按
{
Str_Key->Key_Press_Type = KEY_LONG_MODE;
}
else if(Str_Key->KFilter > Str_Key->Key_Single_TimeSet) //短按
{
if(Str_Key->Key_Single_Cnt==1) Str_Key->Key_Press_Type = KEY_Single_MODE;
}
Str_Key->Key_Single_Cnt=0;
Str_Key->KFilter = 0;
Str_Key->Key_Long_Up = 0;
Str_Key->Key_Down_OK = 0;
}
else if(Str_Key->Key_Down_OK) //长按按键未松开需要蜂鸣器报警
{
if(Str_Key->KFilter == Str_Key->Key_SP_Long_TimeSet)//5S长按
{
*beep_status = KEY_SP_LONG_MODE;
}
else if(Str_Key->KFilter == Str_Key->Key_Long_TimeSet) //2S长按
{
*beep_status = KEY_LONG_MODE;
}
else if(Str_Key->KFilter == Str_Key->Key_Single_TimeSet) //短按
{
*beep_status = KEY_Single_MODE;
}
}
}
按键扫描函数大体分为两部分,一部分是是否按下按键的判断, 一部分是按键时间的判断。
按键时间超过2秒,5秒,给蜂鸣器一个事件标志位,用蜂鸣器的声响来判断目前是否按了2秒或者5秒。
4、按键处理函数
u32 Button_Scan_Status(void)
{
u32 key_status=0;
u8 beep_status=0;
Button_Scan_State(&IOT_Switch,&beep_status);
if(IOT_Switch.Key_Press_Type ==KEY_Single_MODE) key_status |=IOT_Single_EVENT;
else if(IOT_Switch.Key_Press_Type ==KEY_LONG_MODE) key_status |=IOT_LONG_EVENT;
else if(IOT_Switch.Key_Press_Type ==KEY_SP_LONG_MODE) key_status |=IOT_SP_LONG_EVENT;
if(beep_status ==KEY_Single_MODE) key_status |=BEEP_ON_EVENT1; //蜂鸣器1声
else if(beep_status ==KEY_LONG_MODE) key_status |=BEEP_ON_EVENT2; //蜂鸣器2声
else if(beep_status ==KEY_SP_LONG_MODE) key_status |=BEEP_ON_EVENT3; //蜂鸣器3声
//清除按键标志位
IOT_Switch.Key_Press_Type =0;
return key_status;
}
在按键处理函数中,对刚才的按键时间标志位和蜂鸣器标志位做出判断。之后返回让上层应用进行处理。
5、按键执行函数
void Button_Iot_Handle(u32 key_mode)
{
if((key_mode & IOT_Single_EVENT) == IOT_Single_EVENT)
{
printf("key single\r\n");
}
else if((key_mode & IOT_LONG_EVENT) == IOT_LONG_EVENT)
{
printf("key long\r\n");
}
else if((key_mode & IOT_SP_LONG_EVENT) == IOT_SP_LONG_EVENT)
{
printf("key sp long\r\n");
}
}
此处key_mode为上一步按键处理函数所返回的值