按键控制,按键双击,长按,单击

STM32F103按键控制
按键双击,长按有效,单击取消
在学习过程中需要完成稍微复杂一点的功能,按键又不想设计太多(主要节省成本)


在工程中主要有以下几个步骤
一、按键初始化
1、初始化按键IO引脚,这里配置的是上拉输入
2、编写单个按键检测程序(加延时消抖)
3、宏定义每个按键的状态值Key_State
4、编写判断是否有按键按下函数,并确定此按键的状态值
5、编写按键功能函数
二、定时器初始化

1、选择通用定时器
2、配置定时器时间,并开启中断
3、编写中断服务函数

//宏定义每个按键的状态值Key_State
#define KEY1_STATE_VALUE	(0x0001)
#define KEY2_STATE_VALUE	(0x0002)
#define KEY3_STATE_VALUE	(0x0004)
#define KEY4_STATE_VALUE	(0x0008)
 
#define KEY5_STATE_VALUE	(0x0010)
#define KEY6_STATE_VALUE	(0x0020)
#define KEY7_STATE_VALUE	(0x0040)
#define KEY8_STATE_VALUE	(0x0080)
 
#define KEY9_STATE_VALUE	(0x0100)
#define KEY10_STATE_VALUE	(0x0200)
#define KEY11_STATE_VALUE	(0x0400)
#define KEY12_STATE_VALUE	(0x0800)
 
//按键延时超时值
#define Key_Two_Click_Time		200 //200以内双击有效输出
#define Key_Long_Click_Time		300 //长按300及以上有效输出
 
 
uint16_t Key_State = 0; 		//按键状态值
 
uint8_t Key_Value = 0;			//按键按下去的值
uint8_t Old_Key_Value = 0;		//上一次按键按下去的值
 
uint8_t Key_Ture_Value = 0;		//最终输出的值
uint8_t Old_Key_Ture_Value = 0;	//上一次最终输出的值
 
uint8_t Key_Down_Count_Flag = 0;//按键按下次数的值,用于判断是单击还是双击
 
uint8_t Key_Down_Flag = 0;		//按键按下标志位,防止一直按着导致按键次数一直增加
 
uint16_t Key_Click_Time = 0;	//按键次数为1时开始计时,其他状态为0
 
 
 
void Key_Init(void) //初始化12个按键引脚
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
		
	GPIO_InitStructure.GPIO_Pin = KYE10_GPIO_PIN|
								  KYE8_GPIO_PIN|
								  KYE7_GPIO_PIN|
								  KYE6_GPIO_PIN|
								  KYE5_GPIO_PIN|
								  KYE4_GPIO_PIN|
								  KYE3_GPIO_PIN|
								  KYE1_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);	
	
	GPIO_InitStructure.GPIO_Pin = KYE2_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = KYE9_GPIO_PIN|KYE11_GPIO_PIN|KYE12_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(GPIOC,&GPIO_InitStructure);	
}
 
/*
* 描述:  返回key1控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key1_State(void)
{
	if(GPIO_ReadInputDataBit(KEY1_GPIO,KYE1_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY1_GPIO,KYE1_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
 
/*
* 描述:  返回key2控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key2_State(void)
{
	if(GPIO_ReadInputDataBit(KEY2_GPIO,KYE2_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY2_GPIO,KYE2_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
 
/*
* 描述:  返回key3控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key3_State(void)
{
	if(GPIO_ReadInputDataBit(KEY3_GPIO,KYE3_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY3_GPIO,KYE3_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
 
/*
* 描述:  返回key4控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key4_State(void)
{
	if(GPIO_ReadInputDataBit(KEY4_GPIO,KYE4_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY4_GPIO,KYE4_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
 
/*
* 描述:  返回key5控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key5_State(void)
{
	if(GPIO_ReadInputDataBit(KEY5_GPIO,KYE5_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY5_GPIO,KYE5_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
/*
* 描述:  返回key6控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key6_State(void)
{
	if(GPIO_ReadInputDataBit(KEY6_GPIO,KYE6_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY6_GPIO,KYE6_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
/*
* 描述:  返回key7控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key7_State(void)
{
	if(GPIO_ReadInputDataBit(KEY7_GPIO,KYE7_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY7_GPIO,KYE7_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
 
/*
* 描述:  返回key8控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key8_State(void)
{
	if(GPIO_ReadInputDataBit(KEY8_GPIO,KYE8_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY8_GPIO,KYE8_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
 
 
/*
* 描述:  返回key9控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key9_State(void)
{
	if(GPIO_ReadInputDataBit(KEY9_GPIO,KYE9_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY9_GPIO,KYE9_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
/*
* 描述:  返回key10控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key10_State(void)
{
	if(GPIO_ReadInputDataBit(KEY10_GPIO,KYE10_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY10_GPIO,KYE10_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
/*
* 描述:  返回key11控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key11_State(void)
{
	if(GPIO_ReadInputDataBit(KEY11_GPIO,KYE11_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY11_GPIO,KYE11_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
/*
* 描述:  返回key12控制键的状态  
* 参数:  无
* 返回值:0按下 1没按下
*/
uint8_t Get_Key12_State(void)
{
	if(GPIO_ReadInputDataBit(KEY12_GPIO,KYE12_GPIO_PIN) == RESET)
	{
		Delay_Ms(10);
		if(GPIO_ReadInputDataBit(KEY12_GPIO,KYE12_GPIO_PIN) == RESET)
		{
			return 0;
		}	
	}
	return 1;
}
/*
*描述:		判断只有一个按键按下
*参数:		无
*返回值:	1:有按键按下,0:无按键按下
*/
uint8_t Key_Down_Num(void)
{
	if(0 == Get_Key1_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key1_State())
		{
			Key_State |= KEY1_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY1_STATE_VALUE;
	}
 
///
	if(0 == Get_Key2_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key2_State())
		{
			Key_State |= KEY2_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY2_STATE_VALUE;
	}
 
///
	if(0 == Get_Key3_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key3_State())
		{
			Key_State |= KEY3_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY3_STATE_VALUE;
	}
 
///
	if(0 == Get_Key4_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key4_State())
		{
			Key_State |= KEY4_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY4_STATE_VALUE;
	}
 
///
	if(0 == Get_Key5_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key5_State())
		{
			Key_State |= KEY5_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY5_STATE_VALUE;
	}
 
///
	if(0 == Get_Key6_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key6_State())
		{
			Key_State |= KEY6_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY6_STATE_VALUE;
	}
 
///
	if(0 == Get_Key7_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key7_State())
		{
			Key_State |= KEY7_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY7_STATE_VALUE;
	}
 
///
	if(0 == Get_Key8_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key8_State())
		{
			Key_State |= KEY8_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY8_STATE_VALUE;
	}
 
///
	if(0 == Get_Key9_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key9_State())
		{
			Key_State |= KEY9_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY9_STATE_VALUE;
	}
 
///
	if(0 == Get_Key10_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key10_State())
		{
			Key_State |= KEY10_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY10_STATE_VALUE;
	}
 
///
	if(0 == Get_Key11_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key11_State())
		{
			Key_State |= KEY11_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY11_STATE_VALUE;
	}	
	
///
	if(0 == Get_Key12_State())
	{
		Delay_Ms(10);
		if(0 == Get_Key12_State())
		{
			Key_State |= KEY12_STATE_VALUE;
		}
	}
	else
	{
		Key_State &= ~KEY12_STATE_VALUE;
	}	
///	
	Key_State &= 0x0fff;
	if(Key_State != 0)
	{
		return 1;
	}
	return 0;	
}
 
/*
*描述:		按键检测
*参数:		无
*返回值:	无
*/
void Key_Scanf(void)
{
	if(1 == Key_Down_Num())//判断是否有按键按下
	{
		Old_Key_Value = Key_Value; //每一次按下记录上一次按键的值
		switch(Key_State) //判断按键状态值
		{
			case KEY1_STATE_VALUE:Key_Value = 1;break;
			case KEY2_STATE_VALUE:Key_Value = 2;break;
			case KEY3_STATE_VALUE:Key_Value = 3;break;
			case KEY4_STATE_VALUE:Key_Value = 4;break;
			case KEY5_STATE_VALUE:Key_Value = 5;break;
			case KEY6_STATE_VALUE:Key_Value = 6;break;
			case KEY7_STATE_VALUE:Key_Value = 7;break;
			case KEY8_STATE_VALUE:Key_Value = 8;break;						
			case KEY9_STATE_VALUE:Key_Value = 9;break;		
			case KEY10_STATE_VALUE:Key_Value = 10;break;
			case KEY11_STATE_VALUE:Key_Value = 11;break;
			case KEY12_STATE_VALUE:Key_Value = 12;break;			
			default:Key_Value = 0;break;			
		}		
		if(Key_Down_Flag == 1)
		{
			Key_Down_Count_Flag++; //记录按键按下去的次数			
		}
		Key_Down_Flag = 0;		
	}
	else
	{
		Key_Down_Flag = 1;
	}
	
}
 
/*
*描述:判断是否是有效键值
*参数:无
*返回值:无
*/
void GetKey_True_Touch(void)
{
	if(Key_Down_Count_Flag == 1) //按下1次
	{
		if(Key_Down_Flag == 0) //按键按下
		{
			//定时器超过长按规定时间
			if(Key_Click_Time >= Key_Long_Click_Time)
			{
				Key_Ture_Value = Key_Value;
			}
			else
			{
				Key_Ture_Value = 0;
			}			
		}
		else	///按键松开
		{
			//判断定时器时间是否超过规定时间
			//如果超过规定时间,清零变量
			if(Key_Click_Time > Key_Two_Click_Time)
			{
				Key_Ture_Value = 0;				//输出值清零				
				Key_Click_Time = 0;				//定时器时间清零
				Key_Down_Count_Flag = 0;	//按键次数清零
			}
		}	
	}
	else if(Key_Down_Count_Flag == 2)//按下2次
 	{
		//如果两次按键值相等,说明双击的是同一个按键
		//如果两次按键值不相等,输出0;
		if(Old_Key_Value == Key_Value)
		{
			Key_Ture_Value = Key_Value;
		}
		else
		{
			Key_Ture_Value = 0;				//输出值清零	
		}
		Key_Click_Time = 0;				//定时器时间清零
		Key_Down_Count_Flag = 0;	//按键次数清零
		while(Key_Down_Num());    //等待按键松开
	}
	
}
 
//定时器配置//
 
void TIM2_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;	
	NVIC_InitTypeDef 				NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	
	//配置周期为5ms
	TIM_TimeBaseInitStructure.TIM_Period = 4999;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ARRPreloadConfig(TIM2,ENABLE);//在ARR上启用或禁用TIMx外设预加载寄存器。
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	TIM_Cmd(TIM2,ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
	
	NVIC_Init(&NVIC_InitStructure);
}	
//中断服务函数
void TIM2_IRQHandler(void)
{
	while(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update))
	{
		//按键单击,双击,长按监测
		if(Key_Down_Count_Flag == 1)
		{
			Key_Click_Time++;
			if(Key_Click_Time > Key_Long_Click_Time)
			{
				Key_Click_Time = Key_Long_Click_Time;
			}			
		}
		else
		{
				Key_Click_Time = 0;
		}
		TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
	}	
}


原文链接:https://blog.csdn.net/zhai17863966493/article/details/104415911

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
51单片机实现电水壶按键函数可以参考以下步骤: 1. 定义按键引脚:根据电路设计,定义按键所连接的引脚。 2. 初始化按键引脚:将按键所连接的引脚设置为输入模式,初始状态为高电平。 3. 读取按键状态:循环读取按键引脚的状态,如果检测到低电平,说明按键被按下。 4. 消抖处理:由于按键的机械结构特性,当按键被按下时,可能会产生抖动,需要进行消抖处理。 5. 判断按键功能:根据电路设计,判断当前按下的按键是哪个,执行相应的功能。 6. 等待按键释放:在执行完按键功能后,等待按键被释放,重新进入读取按键状态的循环。 以下是一个简单的电水壶按键函数例子: ```c #include <reg51.h> // 51单片机头文件 #define KEY P1 // 按键所连引脚 void InitKey(void) // 初始化按键引脚 { KEY = 0xFF; // 设置为输入模式,初始状态为高电平 } unsigned char ReadKey(void) // 读取按键状态 { unsigned char keyVal = 0xFF; // 初始值为高电平 unsigned char i; if (KEY != 0xFF) // 检测到低电平,说明按键被按下 { Delay(5); // 延时一段时间,进行消抖处理 if (KEY != 0xFF) // 再次检测按键状态 { keyVal = KEY; // 获取按键值 while (KEY != 0xFF); // 等待按键释放 switch (keyVal) // 判断按键功能 { case 0xFE: // 第一个按键 // 执行相应的功能 break; case 0xFD: // 第二个按键 // 执行相应的功能 break; // ... default: break; } } } return keyVal; } void main(void) { InitKey(); // 初始化按键引脚 while (1) { ReadKey(); // 读取按键状态 } } ``` 这里只是一个简单的例子,具体的实现根据电路设计和功能需求进行相应的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值