蓝桥杯嵌入式G431(hal库)——定时器实现按键长按、短按、双击

前言:

        本文使用cubemx软件,利用定时器10ms中断实现按键的长按、短按、双击。

        定时器通常是通过一个晶体振荡器和一个计数器实现的。晶体振荡器可以产生稳定的时间基准,计数器可以根据振荡器提供的稳定时钟信号进行计数。当计数达到预设的值时,计数器就会触发一个中断信号。通过调整计数器的预设值和时钟信号的频率,我们就可以实现不同时间间隔的定时器。

        例如,我们的频率为80MHz,我们可以将分频系数设置为80-1,重装载值设置为10000-1,则中断时间为80000000/80/10000=100HZ,1/100=0.01秒,即10ms。

        定时器10ms进入一次中断,回调函数中读取引脚电平状态,由于按键抖动不会超过10ms,通过多次引脚电平保持时长进行判断,可实现短按、长按、双击。

CUBEMX配置如下:

        时钟树配置:

        定时器配置(蓝桥杯选手建议使用TIM6):

        记得开启NVIC:

        引脚配置为输入状态即可。

 代码如下:

        开启定时器中断代码如下:

    HAL_TIM_Base_Start_IT(&htim6);

        中断回调函数如下:


struct keystruct {
    uint8_t keyLevel;
    uint8_t keyShort;
    uint8_t keyLong;
    uint8_t KeyDouble;
    uint8_t keyTime1;
    uint8_t keyTime2;
    uint8_t keyChoose;
}key[4];

 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    key[0].keyLevel=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
    key[1].keyLevel=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
    key[2].keyLevel=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
    key[3].keyLevel=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
    for(int i=0;i<4;i++)
    {
        switch(key[i].keyChoose)
        {
            case 0:
                if(key[i].keyLevel==0)            
                    key[i].keyChoose=1;                //按下
                break;
            case 1:                                                    
                if(key[i].keyLevel==0)            
                    key[i].keyChoose=2;                //消抖            
                else
                    key[i].keyChoose=0;                    //去抖
                break;
            case 2:
                if(key[i].keyLevel==0)              //单击计时
                    key[i].keyTime1++;                     
                else 
                    key[i].keyChoose=3;           //已松手 
                break;
            case 3:
                    if(key[i].keyLevel==1)    
                    {
                        key[i].keyTime2++;                //等待双击开始计时
                        if(key[i].keyTime2>30)        // 等待时间过长,长按短按判断
                        {
                            if(key[i].keyTime1<70)
                                    key[i].keyShort=1;            //是短按
                            else
                                    key[i].keyLong=1;                    //长按
                            key[i].keyChoose=0;                    //清除标志
                            key[i].keyTime1=0;
                            key[i].keyTime2=0;
                        }
                    }
                    else
                        key[i].keyChoose=4;                //双击开始
                break;
            case 4:    
                if(key[i].keyLevel==0)            //不是消抖
                    key[i].keyChoose=5;        
                else                                                //是抖动
                {
                    if(key[i].keyTime1<70)
                            key[i].keyShort=1;            //是短按
                    else
                            key[i].keyLong=1;                    //长按
                    key[i].keyChoose=0;
                    key[i].keyTime1=0;
                    key[i].keyTime2=0;    
                }                    
                break;
            case 5:
                    if(key[i].keyLevel==1)            //双击松手
                    {
                        key[i].KeyDouble=1;
                        key[i].keyChoose=0;
                        key[i].keyTime1=0;
                        key[i].keyTime2=0;    
                    }
                break;
        }
    }
}

        屏幕显示代码如下:

void keyProc(void)
{
    char chPorc[21];
    for(int i=0;i<4;i++)
    {
        if(key[i].keyShort==1)
        {
            key[i].keyShort=0;
            sprintf(chPorc,(const char *)"KEY SHORT = %d    ",i+1);
            LCD_DisplayStringLine(Line2,(u8 *)chPorc);
        }
        if(key[i].keyLong==1)
        {
            key[i].keyLong=0;
            sprintf(chPorc,(const char *)"KEY  LONG = %d    ",i+1);
            LCD_DisplayStringLine(Line2,(u8 *)chPorc);
        }
        if(key[i].KeyDouble==1)
        {
            key[i].KeyDouble=0;
            sprintf(chPorc,(const char *)"KEY DOUBLE = %d    ",i+1);
            LCD_DisplayStringLine(Line2,(u8 *)chPorc);

        }
        
    }
}

最后

        mian函数中调用一下即可

链接

        链接:https://pan.baidu.com/s/1-tUgoAmMSVSJ0tivBjPNJQ?pwd=la74 
        提取码:la74

        

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值