STM32按键长按短按控制LED灯闪烁 同时可以按一下键切换一下状态

STM32程序:按键长按和短按的判断,用来控制LED灯,有借鉴了其他程序,但是有细节上的不同。短按是切换灯亮的状态,每按一下换一个状态,长按led灯快闪并且指示灯向4靠近,直到等于4是慢闪。如果只做长短按不需要注重里面内容。这里就不细说了,不懂可以评论。

(因为这里做的按键是速度,所以写的SP,根据自己情况自己定义就好)

用定时器中断定时,配置部分就不写了,都差不多
time_key.c

 void TIM3_IRQHandler(void)   //TIM3ÖжÏ
  {
	if (TIM_GetITStatus(TIM3, TIM_IT_Update)==1)  
		{ 	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);	 
							 SP_nTime=1;//用于判断长按短按的定时	
							 SP_delay=1;//用于做灯闪烁延迟的标志位
		}
	}
	

这里是重点,判断长按还是短按,这里程序只写主要的部分,一些配置部分就不写了
key.c

u8 Key_SP_state()
{
	 if( (SP_nTime_count == 0) && (SP_key_value != ANG_KEY_NULL))
	 {
//		SP_key_value = SP_KEY_NULL;    //因为这里我要在主函数里面做循环用来让led灯闪烁,所以这里不可以清零键值,但是不需要闪烁的话最好可以清零
	 }
	 if(SP_nTime==1) //5ms     是一个5ms 源自定时器
	 {
		 SP_nTime=0;     //归零用于判断是否是下一个5ms
		 if((SP_SELECT==0))  //按键按下的状态
		 {
			 SP_nTime_count++;    //计数5ms的次数 用于定时
		 }
	 else                 //按键松开  可以看计时的时间
	 {
	 if((SP_nTime_count > 0) && (SP_nTime_count <=100))  //5ms次数在0到100  就是按键时间在0到500ms  是短按
			{
				SP_key_value = SP_KEY_SHORT;//赋键值
				SP_nTime_count = 0;   //计数清零
			}
			else if( SP_nTime_count > 400) //按键时间大于2s
			{
			 SP_key_value = SP_KEY_LONG; //赋键值
			 SP_nTime_count = 0; //计数清零
			}
			else  //用于去抖动 
			{
//			  SP_key_value = SP_KEY_NULL; //因为这里我要做循环用来让了led灯闪烁,所以这里不可以清零键值,但是不需要闪烁的话最好可以清零(同上)
				SP_nTime_count = 0; //
			}
			SP_nTime_count = 0; //清零
		}
	}
	 return SP_key_value;	//返回键值
}

接下来就是主函数当中的调用了,同样,配置部分就不写了。
main.c

		Key_SP_state();
		//短按你要执行的程序
		if(SP_key_value==SP_KEY_SHORT)    
		{
			if(SP_key_count==0)
			{
				SP_key_value=SP_KEY_NULL;
				SP_key_count=1;
			  SP_LED_G_H;
		 	  SP_LED_R_L;
			}
    else if(SP_key_count==1)
			{
			SP_key_value=SP_KEY_NULL;
			SP_key_count=0;
			SP_LED_G_H;
			SP_LED_R_H;
		}
		}
//长按 写你要执行的程序   这里是要循环 所以键值不能变化 确保下次还是成立IF  
// 下面程序目的为标准速度指示灯为标志4,当长按时,led灯快闪并且指示灯向4靠近,
//直到等于4是慢闪。如果只做长短按不需要注重里面内容。这里就不细说了,不懂可以评论。
 else if(SP_key_value==SP_KEY_LONG)
		{
			SP_key_count=1;
			if(SP_delay==1)
			{
			  SP_delay_count++;
				SP_delay=0;
			}
//			ANG_key_value=ANG_KEY_NULL;
				if(led_SP==4)//led灯号标志位=4
				{
				if(SP_delay_count==200)
				{
				SP_LED_R_H;
				SP_LED_G_L;		
				}
				if(SP_delay_count==400)
				{
				SP_delay_count=0;
				SP_LED_R_L;
				SP_LED_G_L;
				}
				if(SP_delay_count>400)
				{
				SP_key_value=SP_KEY_NULL;
				SP_delay_count=0;
				}
        }
			if(led_SP>4)
	   	{
				if(SP_delay_count==60)
				{
				SP_LED_R_H;
				SP_LED_G_L;	
				}
				if(SP_delay_count==120)
				{
					SP_delay_count=0;
				SP_LED_R_L;
				SP_LED_G_L;	
				led_SP--;//led灯号标志位
				}
				if(SP_delay_count>120)
				{
				SP_key_value=SP_KEY_NULL;
				SP_delay_count=0;
				}
			}
			if(led_SP<4)
				{

				if(SP_delay_count==60)
				{
				SP_LED_R_H;
				SP_LED_G_L;		
				}
				if(SP_delay_count==120)
				{
				SP_delay_count=0;
				SP_LED_R_L;
				SP_LED_G_L;	
				led_SP++;//led灯号标志位
				}
				if(SP_delay_count>120)
				{
				SP_key_value=SP_KEY_NULL;
				SP_delay_count=0;
				}
				}

		}

这次的程序就写到这里。

  • 9
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实现按键按、短按和组合按键功能可以通过状态机来实现。下面提供一个简单的示例代码,以两个按键为例,一个为K1,一个为K2。 首先定义状态: ```c typedef enum { KEY_IDLE_STATE, KEY_SHORT_PRESS_STATE, KEY_LONG_PRESS_STATE, KEY_COMB_PRESS_STATE } KEY_STATE; ``` 然后定义按键结构体: ```c typedef struct { GPIO_TypeDef *port; uint16_t pin; uint32_t long_press_time; uint32_t comb_press_time; uint32_t last_time; uint8_t comb_flag; KEY_STATE state; } KEY_TypeDef; ``` 其中,`port`和`pin`表示按键所在的GPIO口和引脚,`long_press_time`表示按的时间阈值,`comb_press_time`表示组合按键的时间阈值,`last_time`表示上次检测按键的时间,`comb_flag`表示组合按键标志,`state`表示当前状态。 接下来定义状态转换函数: ```c static void key_state_transfer(KEY_TypeDef *key) { uint32_t current_time = HAL_GetTick(); switch (key->state) { case KEY_IDLE_STATE: if (HAL_GPIO_ReadPin(key->port, key->pin) == GPIO_PIN_RESET) { key->state = KEY_SHORT_PRESS_STATE; key->last_time = current_time; } break; case KEY_SHORT_PRESS_STATE: if (HAL_GPIO_ReadPin(key->port, key->pin) == GPIO_PIN_SET) { key->state = KEY_IDLE_STATE; if (current_time - key->last_time < key->long_press_time) { // 短按 } else { // 按 } } else { if (current_time - key->last_time >= key->comb_press_time) { key->state = KEY_COMB_PRESS_STATE; key->comb_flag = 1; } } break; case KEY_LONG_PRESS_STATE: if (HAL_GPIO_ReadPin(key->port, key->pin) == GPIO_PIN_SET) { key->state = KEY_IDLE_STATE; } break; case KEY_COMB_PRESS_STATE: if (HAL_GPIO_ReadPin(key->port, key->pin) == GPIO_PIN_SET) { key->state = KEY_IDLE_STATE; if (key->comb_flag) { // 组合按键 } key->comb_flag = 0; } break; default: key->state = KEY_IDLE_STATE; break; } } ``` 在主函数中循环调用按键状态转换函数即可: ```c KEY_TypeDef key1 = { GPIOA, GPIO_PIN_0, 1000, 500, 0, 0, KEY_IDLE_STATE }; KEY_TypeDef key2 = { GPIOA, GPIO_PIN_1, 1000, 500, 0, 0, KEY_IDLE_STATE }; while (1) { key_state_transfer(&key1); key_state_transfer(&key2); } ``` 上述代码实现了两个按键按、短按和组合按键功能,你可以根据实际需要进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值