嵌入式按键驱动,支持短按、长按、双击(轮询方式)

目录:

1:概述

2:代码功能

3:代码分享


概述:

代码利用轮询方式对按键状态进行扫描,扫描得出按键的键值(短按、长按、双击),然后根据键值进行相应的事件处理;

平台:奋斗STM32F103 V5开发板  开发环境:KEIL MDK5


代码功能:

短按K1按键,LED1灯闪烁,闪烁间隔250ms;

长按K1按键1.5S以上,三个LED同时闪烁,闪烁间隔250ms;

双击K1按键,实现三个LED的流水灯;


代码分享:

main.c函数:

/*
*FUNC:轮询按键键值,实现按键短按(单击)、长按、双击功能
*MCU:stm32f103
*DATE:2016/10/07
*/
#include "Key_Board.h"
#include "Rcc_Driver.h"
#include "Led_Driver.h"
#include "Sysclk_Driver.h"

/*led闪烁标志 为1--led亮 为0--led灭*/
bool led_flag = 0;
bool led1_flag = 0;

/*任务:led闪烁时间间隔*/
volatile unsigned int led_flash_timing = 0;

/*任务:按键轮询时间间隔*/
volatile unsigned int key_scan_timing = 0;
unsigned char i = 0;

int main()
{
	RCC_PeriphClock_Config();                              //模块时钟初始化
	Key_Init();                                            //按键初始化  
	Led_Init();                                            //按键初始化
	SysTick_Init(INT_1MS,SysTick_CLKSource_HCLK_Div8);     //内核滴答定时器配置

	while(1)
	{
		/*任务1:10ms进行一次按键键值扫描和按键事件处理*/
		if(key_scan_timing > 10)
		{
			key_scan_timing = 0;
			Key_Scan();           //扫描按键是否按下,上报按键键值
			Key_Func();           //根据按键键值,对应事件的标志位置1
		}
		
		/*任务2:完成led闪烁*/
		if(led_flash_timing > 250)
		{
			led_flash_timing = 0;
			if(led_water_flag == 1)     //led流水灯:LED1 LED2 LED3
			{
				if(++i > 3)
					i = 1;
				switch(i)
				{
					case 1:
						LED1_ON;
						LED3_OFF;
						break;
					case 2:
						LED2_ON;
						LED1_OFF;
						break;
					case 3:
						LED3_ON;
						LED2_OFF;
						break;
				}
			}
			else
			if(led_all_flash_flag == 1)    //LED1 LED2 LED3同时闪烁
			{
				led_flag = !led_flag;
				if(led_flag==1)
				{
					LED1_ON;
					LED2_ON;
					LED3_ON;
				}
				else
				{
					LED1_OFF;
					LED2_OFF;
					LED3_OFF;
				}
			}
			else
			if(led1_flash_flag==1) //LED1闪烁
			{
				led1_flag = !led1_flag;
				if(led1_flag==1)
				{
					LED1_ON;
				}
				else
				{
					LED1_OFF;
				}
			}
			else    //当没有按键事件需要处理时,熄灭三个led灯
			{
				LED1_OFF;
				LED2_OFF;
				LED3_OFF;
			}
		}
	}
}



按键扫面函数(Key_Scan(void))和按键事件处理函数(Key_Func(void)):

Key_Board.c:

#include "Key_Board.h"

/*记录按键按下时间 时间小于1.5S,按键为短按;时间大于1.5S,按键为长按*/
volatile unsigned int key1_timing = 0;

/*记录两次短按之间的时间间隔*/
volatile unsigned int key1_doublepress_timing = 0;

/*定义按键键值结构体*/
Key_Value k1_value;

/*K1按键短按标志位*/
bool k1_shortpress_happen = 0;

/*K1按键长按标志位*/
bool k1_longpress_happen = 0;

/*K1按键双击标志位*/
bool k1_doublepress_happen = 0;

/*led1闪烁时间标志位,主函数检测到此标志位为1时,led1开始闪烁,否则,结束闪烁*/
bool led1_flash_flag = 0;

/*3个led全部闪烁标志位,主函数检测到此标志为1时,三个led灯开始同时闪烁,否则结束闪烁*/
bool led_all_flash_flag = 0;

/*流水灯事件标志位*/
bool led_water_flag = 0;

/*按键初始化
*设置GPIOC2/GPIOC3/GPIOC5为上拉输入,按键按下为低电平,按键抬起为高电平
*/
void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_5;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
}

/*按键键值扫描函数*/
void Key_Scan(void)
{
	/*程序不支持两个按键同时按下*/
//	if((K1==0&&K2==0) || (K1==0&&K3==0) || (K2==0&&K3==0))
//		return ;
	
	if(K1==0)         //当K1按键按下
	{
		if(k1_shortpress_happen==0)
		{
			k1_shortpress_happen = 1;      //开始一次按键键值扫描
			key1_timing = 0;               //按键按下计时变量清0,开始计时,此值每1ms加1,sysclk中断函数中实现自加
		}
		
		if(k1_shortpress_happen==1)
		{
			if(key1_timing > 1500)         //按键按下时间超过1.5S,长按事件发生,置k1_value.long_press为1
			{
				k1_value.long_press = 1;
				k1_shortpress_happen = 0;    //按键短按标志位置0
			}
		}
	}
	
	if(K1==1)         //当K1按键抬起
	{
		if(k1_shortpress_happen==1)      //按键抬起后,k1_shortpress_happen等于1,说明按键为短按,不是长按
		{
			k1_shortpress_happen = 0; 
			if(k1_doublepress_happen==0)
			{
				k1_doublepress_happen = 1;    //按键双击标志位置1,等待确认按键是否为双击
				key1_doublepress_timing = 0;  //开始计时,同样1ms自增加1
			}
			else
			{
				if(key1_doublepress_timing < 500)  //第一次短按发生后,在500ms时间内,发生第二次短按,完成一次双击,跟新按键键值
				{
					k1_doublepress_happen = 0;
					k1_value.double_press = 1;
				}
			}
		}
		else
		if(k1_doublepress_happen == 1)         //第一次短按后,等待500ms,如未再发生短按,跟新按键短按键值
		{
			if(key1_doublepress_timing > 500)
			{
				k1_doublepress_happen = 0;
				k1_value.short_press = 1;
			}
		}
		else
		if(k1_longpress_happen==1)
			k1_longpress_happen = 0;
	}
}

/*按键事件处理函数 根据键值 进行相应的事件处理*/
void Key_Func(void)
{
		if(k1_value.short_press == 1)
		{
			k1_value.short_press = 0;
			//led1_flash_flag = (led1_flash_flag==TRUE? FALSE:TRUE);
			led1_flash_flag = !led1_flash_flag;
		}
		
		if(k1_value.long_press == 1)
		{
			k1_value.long_press = 0;
			//led_all_flash_flag = (led_all_flash_flag==TRUE?FALSE:TRUE);
			led_all_flash_flag = !led_all_flash_flag;
		}
		
		if(k1_value.double_press == 1)
		{
			k1_value.double_press = 0;
			//led_water_flag = (led_water_flag==TRUE?FALSE:TRUE);
			led_water_flag = !led_water_flag;
		}
}





版权声明:本文为Golf_research原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。