【蓝桥杯嵌入式】stm32三种按键(短按,长按,双击)一起实现

本文介绍了如何在STM32嵌入式开发中使用Cubemx配置TIM6定时器,以10ms周期检测按键状态,并处理按键的长按、短按和双击事件。通过HAL库实现了按键事件的处理逻辑。
摘要由CSDN通过智能技术生成
  1. 附上我的keil工程和cubemx工程
    1. 链接:https://pan.baidu.com/s/1iEmh_VOZfRK-eUi_VVicgA?pwd=gnjx 
      提取码:gnjx
  2. 基本的略讲了
    1. stm32cubemx的时钟树
    2. 定时器我们使用TIM6,因为我们的时钟频率为80x10的6次方,则我们需要每10ms进入定时器进行判断,则我们的psc设置为800-1,arr设置为1000-1,80000000/800/1000=100hz,因次同时打开TIM6的NVIC中断
  3. 按键处理部分(参考了

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    本文链接:蓝桥杯嵌入式G431(hal库)——定时器实现按键长按、短按、双击_hal库单击,双击和长按控制灯状态的报告-CSDN博客

    )在此基础上修改了一点。
    1. 首先,重新定义定时器的回调函数,因为在官方中的回调函数是弱定义,因此可以重新定义。回调函数是这个
      void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

    2. 主函数while(1)外面用的代码

      	HAL_TIM_Base_Start_IT(&htim6);
      	
      	LCD_Init();
      	LCD_Clear(Black);
      	LCD_SetBackColor(Black);
      	LCD_SetTextColor(White);

      while(1)里面的代码

        while (1)
        {
      
      		if (key[0].key_short == 1)
      		{
      			key[0].key_short = 0;
      			i++;
      		}
      		if (key[0].key_long == 1)
      		{
      			key[0].key_long = 0;
      			i--;
      			sprintf(textbuf,"i:%d",i);
      			LCD_DisplayStringLine(Line2,(uint8_t *)textbuf);
      		}
      		if (key[0].key_double == 1)
      		{
      			key[0].key_double = 0;
      			i+=10;
      			sprintf(textbuf,"i:%d",i);
      			LCD_DisplayStringLine(Line2,(uint8_t *)textbuf);
      		}
      		sprintf(textbuf,"i:%d",i);
      		LCD_DisplayStringLine(Line2,(uint8_t *)textbuf);
      
          /* USER CODE END WHILE */
      
          /* USER CODE BEGIN 3 */
        }
      

      这里的key是定义在main.h中的结构体定义的结构体变量

    3. 看代码,代码里有注释,与引用的代码不同的地方是将第四个状态里冗余的代码删除了一些。

      void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
      	if (htim->Instance == TIM6)
      	{
      		key[0].cur_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
      		key[1].cur_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
      		key[2].cur_sta = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
      		key[3].cur_sta = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
              //这里是读取GPIO的状态
      		for(int i=0;i<4;i++){
              //遍历四个按键
      			switch(key[i].key_choose)
      			{
                  // 根据状态处理每个状态需要处理的情况
      				case 0:
                      //开始,就是检查是否按下,是按下的,因此我们跳转到2状态,消抖判断
      					if (key[i].cur_sta == 0)
      						key[i].key_choose = 1;
      					break;
      				case 1:
                      //消抖
      					if (key[i].cur_sta == 0)
      						key[i].key_choose = 2;
      					else
      						key[i].key_choose = 0;
      					break;
      				case 2:
          
      					if (key[i].cur_sta == 0)
                          //这里如果按键还是按下的状态,则长按键的时间加一次
      						key[i].key_time_long++;
      					else
                          //松手后进入双击和单击判断状态
      						key[i].key_choose = 3;//
      					break;
      				case 3:
      					if (key[i].cur_sta == 1)
      					{
                           //如果是松手的状态,则短按的时间++,到达一定阈值,且未到达长按键的阈值,则短按成立,否则长按成立,然后将状态置为0,时间同时清0
      						key[i].key_time_short++;
      						if (key[i].key_time_short>10)
      						{
      							if (key[i].key_time_long<70)
      								key[i].key_short = 1;
      							else
      								key[i].key_long = 1;
      							key[i].key_choose = 0;
      							key[i].key_time_long = 0;
      							key[i].key_time_short = 0;
      							
      						}
      					}
      					else
                          //如果按下的状态,跳转4
      						key[i].key_choose = 4;
      					break;
      				case 4:
                          
      					if (key[i].cur_sta == 0)
      						key[i].key_choose = 5;
                          //如果按下,双击消抖
      					else
      					{
                          //否则,跳回0,时间清0
      						key[i].key_choose=0;
      						key[i].key_time_long = 0;
      						key[i].key_time_short = 0;  
      					}
      					break;
      				case 5:
      					if(key[i].cur_sta == 1)
      					{
                          // 松手了,则双击成立
      						key[i].key_double = 1;
      						key[i].key_choose = 0;
      						key[i].key_time_long = 0;
      						key[i].key_time_short = 0;
      					}
      					break;
      			}
      		}
      	}
      }
      

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值