zero949079783 发表于 2022-5-28 21:50

VSCODE STM32 裸机之按键识别篇---单击---双击----长按

本帖最后由 zero949079783 于 2022-5-28 22:11 编辑

开发环境:VSCODE(gcc编译链)+STM32CubeMX(也可以使用HUAWEI-LiteOS-Studio) 。
代码:Scan_key 链接:https://pan.baidu.com/s/1uXfIR0GFQOBZPl1NfQP08w
提取码:6b0c
Scan_key.h#ifndef   __SCAN_KEY_H__
#define__SCAN_KEY_H__

#include "gpio.h"
#include "tim.h"

#define KEY_ON 0
#define KEY_OFF 1

#define delay_ms(x) HAL_Delay(x)

//KEY控制的引脚
#define KEY0_GPIO_PortGPIOE
#define KEY0_Pin      GPIO_PIN_4
#define KEY0_IN()                         HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)


uint8_t scan_key(void);

#endif



Scan_key.c
#include "Scan_key.h"
#include "led.h"

uint16_t key_time = 0;

void Scan_key_Init(void)
{
      
}

uint8_t scan_key(void)
{
                /*
                              值key_return如下:
                              1---------单击
                              2---------双击
                              3---------长按
                */
                static unsigned char key_state=0;                           //按键状态
                static unsigned char state=0;
                static unsigned char time,time1,time2;   
                static unsigned char key_up_flag=0;                           //按键弹起标志位
                static unsigned char key_return;
               
      if(KEY0_IN() == KEY_ON)      //按键按下消抖
      {
                delay_ms(10);
                if(KEY0_IN() == KEY_ON)
                {
                        HAL_TIM_Base_Start_IT(&htim7); //打开TIM7中断
                        key_state=0;
                }
      }
      else
      {
                delay_ms(10);                                                //按键松开消抖
                if(KEY0_IN() == KEY_OFF)
                {
                        //HAL_TIM_Base_Stop_IT(&htim7); //打开TIM7中断
                        key_state=1;
                        key_up_flag=0;
                }
      }
      
      //这里主要防止,按键在识别长按后,又会执行一遍单击操作
      if((state==0)&&(key_state==0)&&(key_up_flag==0))      
      {
                state=1;
                time=key_time;                                       //记录按键按下的时间为多少,做标记
      }      
      
      if(state==1)
      {
               time1=key_time;
               time2=time1-time;                                 //计算按键按下时长
               
               if(time2>50)                                    //长按判断
               {
                        state=2;
               }
               
               if(key_state==1)                              //按键弹起
         {
            state=3;
            time=key_time;                                  //标志什么时间按键弹起的
         }
      }
      
                if(state==2)                                       //长按
                {
                                        state=0;                                     //重置状态
                                        key_up_flag=1;
                                        key_return=3;
                }
               
                if((state==3)&&(key_up_flag==0))
          {
               time1=key_time;
               time2=time1-time;                        //计算按键弹起后时间
                if(time2>6)                              //判断按键弹起后的时间,超过300ms,则说明为单击
                  {
                      state=0;
                  key_return=1;
                  }   
            else    if(key_state==0)                     //按键弹起后,300ms内又有按键按下
               {
                      state=4;
               }
         }
         if(state==4)
          {
                  if(key_state==1)                        //按键弹起
                  {
                     state=0;
                  key_return=2;
                   }
          }
         
   return key_return;
      
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
                if (htim->Instance== TIM7)
                {
                              key_time++;
                              LED_R_TOG();
//                              if(key_time == 1000)
//                              {
//                                        key_time=0;
//                                        LED_G_TOG();
//                              }
                        
                }
}

main.c
                  if(scan_key() == 1)
                              printf("scan_key() = %d\r\n",scan_key());
               else if(scan_key() == 2)
                                                printf("scan_key() = %d\r\n",scan_key());
               else if(scan_key() == 3)
                                                printf("scan_key() = %d\r\n",scan_key());

BSP_USART.c
#include "BSP_USART.h"

void BSP_USART_Init(void)
{

}

//重定向c库函数printf到串口,重定向后可使用printf函数(GCC)

int _write(int fd, char *ptr, int len)
{         
      HAL_UART_Transmit(&huart1,(uint8_t *)ptr,len,10000);
      return (len);
}



////重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数(GCC)

int _read (int fd, char *ptr, int len)
{
      *ptr=0X00;
      HAL_UART_Receive(&huart1,(uint8_t *)ptr,1,10000);
      return 1;
}


///重定向c库函数printf到串口,重定向后可使用printf函数(KEIL)
//重定义fputc函数
int fputc(int ch, FILE *f)
{         
      HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,10000);
      return (ch);
}



///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数(KEIL)
int fgetc(FILE *f)
{
      int ch;
      HAL_UART_Receive(&huart1,(uint8_t *)&ch,1,10000);
      return (ch);
}


页: [1]
查看完整版本: VSCODE STM32 裸机之按键识别篇---单击---双击----长按