• 蓝桥杯物联网竞赛_STM32L071_18_长短按键检测


    长短按键的检测是国赛题里面遇到的,省赛没出过有两种实方法

    定时器配置:

    定时器的话要比delay准确,其中tim7定时器的准度最高
    在这里插入图片描述

    在这里插入图片描述
    定时器预分配配置32 - 1,计数周期是10000 - 1这样做那么32MHZ/32也就是一秒钟记录10^6的数,计数周期配置10 ^ 4也就是说一个周期花费10 ^ 4/10 ^6秒也就是10ms

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  // 10ms
    	// OLED_ShowString(0, "KEY)");
    	COUNTNUMBER ++;
    }
    

    1、普通按键实现:

    普通按键我用的是矩阵按键模块的B1按键测试的

    在这里插入图片描述

    ROW1与ROW2配置为输入模式上拉,COLUMN1配置输出模式

    void Function_KeyCheck(){
      HAL_GPIO_WritePin(COLUMN1_GPIO_Port, COLUMN1_Pin, GPIO_PIN_RESET);
    	if(HAL_GPIO_ReadPin(ROW1_GPIO_Port, ROW1_Pin) == 0){  // 按键按下
    		HAL_TIM_Base_Start_IT(&htim7);
    		while(HAL_GPIO_ReadPin(ROW1_GPIO_Port, ROW1_Pin) == 0);  // 等待定时器关闭
    		HAL_TIM_Base_Stop_IT(&htim7);
    		if(COUNTNUMBER <= 100) KEYTIMEFLAG = 0;
    		else KEYTIMEFLAG = 1;
    		PRESSTIME = (float) COUNTNUMBER * 1.0 / 100;
    		COUNTNUMBER = 0;
    	}
     
    	HAL_GPIO_WritePin(COLUMN1_GPIO_Port, COLUMN1_Pin, GPIO_PIN_SET);
    	
    }
    

    2、中断按键实现:

    在这里插入图片描述
    在这里插入图片描述

    中断按键设置成上升沿和下降沿都会触发的模式,这样人按下按键就是下降沿这时候开定时器,松开就是上升沿,关定时器

    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){  // 中断按键
    	
    	if(!HAL_GPIO_ReadPin(USER_Key_GPIO_Port, USER_Key_Pin)){  // 下降电平开启定时器
    		HAL_TIM_Base_Start_IT(&htim7);
    	}else{  // 上升电平关闭定时器并检测时间
    		if(COUNTNUMBER <= 100) KEYTIMEFLAG = 0;
    		else KEYTIMEFLAG = 1;
    		PRESSTIME = (float) COUNTNUMBER * 1.0 / 100;
    		COUNTNUMBER = 0;
    		HAL_TIM_Base_Stop_IT(&htim7);
    	}
    }
    

    完整代码:

    Function.c

    #include "Function.h"
    #include "main.h"
    #include "oled.h"
    #include "i2c.h"
    #include 
    #include "tim.h"
    
    unsigned char KEYFLAG = 0;
    unsigned char ARRAY[20];
    char* LONGKEY = "long key press";
    char* SHORTKEY = "short key press";
    unsigned char KEYTIMEFLAG = 2;
    float PRESSTIME = 0;
    
    uint32_t COUNTNUMBER = 0;  // 记录时间,这个区间必须要足够大
    
    void OLED_Write(unsigned char type, unsigned char data){
      unsigned char WriteData[2];
    	WriteData[0] = type;
    	WriteData[1] = data;
    	HAL_I2C_Master_Transmit(&hi2c3, 0x78, WriteData, 2, 0xff);
    }
    void Function_OledInit(unsigned char ms){
      HAL_GPIO_WritePin(OLED_Power_GPIO_Port, OLED_Power_Pin, GPIO_PIN_RESET);
    	HAL_Delay(ms);
    	OLED_Init();
    }
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){  // 10ms
    	// OLED_ShowString(0, "KEY)");
    	COUNTNUMBER ++;
    }
    
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){  // 中断按键
    	
    	if(!HAL_GPIO_ReadPin(USER_Key_GPIO_Port, USER_Key_Pin)){  // 下降电平开启定时器
    		HAL_TIM_Base_Start_IT(&htim7);
    	}else{  // 上升电平关闭定时器并检测时间
    		if(COUNTNUMBER <= 100) KEYTIMEFLAG = 0;
    		else KEYTIMEFLAG = 1;
    		PRESSTIME = (float) COUNTNUMBER * 1.0 / 100;
    		COUNTNUMBER = 0;
    		HAL_TIM_Base_Stop_IT(&htim7);
    	}
    	
    }
    
    
    void Function_KeyCheck(){
      HAL_GPIO_WritePin(COLUMN1_GPIO_Port, COLUMN1_Pin, GPIO_PIN_RESET);
    	if(HAL_GPIO_ReadPin(ROW1_GPIO_Port, ROW1_Pin) == 0){  // 按键按下
    		HAL_TIM_Base_Start_IT(&htim7);
    		while(HAL_GPIO_ReadPin(ROW1_GPIO_Port, ROW1_Pin) == 0);  // 等待定时器关闭
    		HAL_TIM_Base_Stop_IT(&htim7);
    		if(COUNTNUMBER <= 100) KEYTIMEFLAG = 0;
    		else KEYTIMEFLAG = 1;
    		PRESSTIME = (float) COUNTNUMBER * 1.0 / 100;
    		COUNTNUMBER = 0;
    	}
     
    	HAL_GPIO_WritePin(COLUMN1_GPIO_Port, COLUMN1_Pin, GPIO_PIN_SET);
    	
    }
    
    void Function_MyMain(){
    	 Function_KeyCheck();
    	 if(KEYTIMEFLAG != 2){
     
    		 sprintf((char* )ARRAY, "%.2f s", PRESSTIME);
    		 if(KEYTIMEFLAG == 0){
    			 OLED_ShowString(0, (unsigned char* )SHORTKEY);
    		 }else if(KEYTIMEFLAG == 1){
    		   OLED_ShowString(0, (unsigned char* )LONGKEY);
    			  
    		 }
    		 OLED_ShowString(2, ARRAY);
    		 KEYTIMEFLAG = 2;
    	 }
    }
    

    Function.h

    #ifndef __FUNCTION_H__
    #define __FUNCTION_H__
    #include "main.h"
    
    void OLED_Write(unsigned char type, unsigned char data);
    void Function_OledInit(unsigned char ms);
    void Function_MyMain();
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
    
    #endif
    

    效果:

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    【JavaSE】String类基本用法和常见操作
    AIGC之Stable diffusion Version 2_ open_clip.create_model_and_transforms报错问题解决
    Vuex详解
    MasterAlign相机参数设置-增益调节
    前端周刊第十五期
    Loj#3320-「CCO 2020」旅行商问题
    现在考Oracle 19c OCP还需要官方的培训记录吗?
    [矩阵论] Unit 3. 矩阵的分解 - 知识点整理
    负载均衡、反向代理(8月26号)
    leetcode-1.两数之和
  • 原文地址:https://blog.csdn.net/xyint/article/details/139275316