【STM32单片机】STM32单片机按键实现长按、短按处理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、为什么要实现一个按键多个功能?
  • 二、使用步骤
    • 1.开启EXTI中断及NVIC配置
    • 2.外部中断处理
    • 3.定时器中断处理
    • 4.按键处理
    • 5.长按处理
    • 6.短按处理
  • 总结


前言

如何使用按键完成长按、短按,在本文中使用单片机stm32f103c8t6完成。


提示:以下是本篇文章正文内容,下面案例可供参考

一、为什么要实现一个按键多个功能?

在设计过程中会出现功能多余按键的情况,可以通过判断按键的不同状态,进入不同的功能函数。而按键的功能状态可以分为,短按、长按、双击等。

二、使用步骤

1.开启EXTI中断及NVIC配置

代码如下(示例):

	GPIO_EXTILineConfig( KEY_LEFT_GPIO_PortSource ,  KEY_LEFT_GPIO_PinSource) ;
	EXTI_InitStruct.EXTI_Line = KEY_LEFT_EXTI_LINE;
	EXTI_InitStruct.EXTI_LineCmd = ENABLE ;
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt ;
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling ;
	EXTI_Init(&EXTI_InitStruct);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

2.外部中断处理

代码如下(示例):

 void EXTI4_IRQHandler(void)
 {
      if(EXTI_GetITStatus(KEY_LEFT_EXTI_LINE)!=RESET)
      {
        key_LEFT_Value.keyState = KEY_DEBOUNCE;
        EXTI_ClearITPendingBit(KEY_LEFT_EXTI_LINE);
      }
 }

3.定时器中断处理

代码如下(示例):

void TIM3_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
     {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
        
        // 系统时基,每5ms增加一次
        systemTick += 5;
        
        // 处理按键状态机
        process_key(&key_LEFT_Value, KEY_LEFT_GPIO_PORT, KEY_LEFT_GPIO_PIN);
        process_key(&key_RIGHT_Value, KEY_RIGHT_GPIO_PORT, KEY_RIGHT_GPIO_PIN);
    }
}

4.按键处理

代码如下(示例):

void process_key(myKey_ValueTypedef *key, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	     switch(key->keyState)
	      {
        case KEY_DEBOUNCE:
            if((systemTick - key->pressedTime) > DEBOUNCE_TIME) 
            {
                if(!GPIO_ReadInputDataBit(GPIOx, GPIO_Pin)) 
                {
                    key->keyState = KEY_PRESSED;
                    key->pressedTime = systemTick;
                    key->longPressTriggered = 0; // 重置长按标记
                } 
                else
                 {
                    key->keyState = KEY_IDLE;
                }
            }
            break;
            
        case KEY_PRESSED:
            // 持续检测长按条件
            if(!key->longPressTriggered && 
              (systemTick - key->pressedTime) >= LONG_PRESS_THRESHOLD)
               {
                handle_long_press(key);
                key->longPressTriggered = 1; // 标记已触发长按
            }
            
            // 检测释放
            if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin))
             {
                key->keyState = KEY_RELEASED;
            }
            break;
            
        case KEY_RELEASED:
            if(!key->isProcessed) 
            {
                // 未触发长按时才处理短按
                if(!key->longPressTriggered) 
                {
                    handle_short_press(key);
                }
                key->isProcessed = 1;
            }
            
            if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin)) 
            {
                key->keyState = KEY_IDLE;
                key->isProcessed = 0;
                key->pressedTime = 0;
                key->longPressTriggered = 0; // 重置长按标记
            }
            break;
            
        case KEY_IDLE:
        default:
            break;
    }
}

5.长按处理

代码如下(示例):

void handle_long_press(myKey_ValueTypedef *key)
{
  // 添加执行后标记防止重复执行
    if(!key->isProcessed) 
    {
        if(key == &key_LEFT_Value)
        {
            Usart_SendString(DEBUG_USARTx,"AT+HFPANSW\r\n");
        }
        else if(key == &key_RIGHT_Value)
        {
            Usart_SendString(DEBUG_USARTx,"AT+HFPCHUP\r\n");
        }
        key->isProcessed = 1; // 标记已处理
    }
}

6.短按处理

代码如下(示例):

void handle_short_press(myKey_ValueTypedef *key)
{
   if(key == &key_LEFT_Value)
   {
        Usart_SendString(DEBUG_USARTx,"AT+PAUSE\r\n");
    }
    else if(key == &key_RIGHT_Value)
    {
        Usart_SendString(DEBUG_USARTx,"AT+PLAY\r\n");
    }
}

总结

提示:这里对文章进行总结:
定时器3的处理和日常处理一致就不做过多赘述。
注:在设计中要看下引脚的功能,有些引脚记得要开复用哦

你可能感兴趣的:(单片机,stm32,嵌入式硬件)