蓝桥杯嵌入式——按键控制LED

一.按键功能简介

M4开发板包含五个按键,其中一个是Reset按键,另外四个是一般的按键。

 

 

从原理图可以知道,按键B0-B4都是外接上拉电阻到VDD,在按下时接通GND,所以按键弹出时读取到1,按下读取到0;

使用时只需要将按键相关GPIO初始化,然后读取电平进行操作即可。

二.使用cubeMx做按键初始化

(直接初始化为输入模式,No pull)

复制代码
void Key_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PB0 PB1 PB2 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}
复制代码

接着需要使用函数读取按键信号,一般来说,需要做按键消抖,但是测试发现不消抖也没有产生问题,这里还是将消抖加上。

复制代码
unsigned char Key_Scan(void)
{
    if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
    {
        //Key_Delay(10);
        Key_Val = 8;
    }
    else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET)
    {
        //Key_Delay(10);
        Key_Val = 1;
    }
    else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)
    {
        //Key_Delay(10);
        Key_Val = 2;
    }
    else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
    {
        //Key_Delay(10);
        Key_Val = 4;
    }
    else
        Key_Val = 0;
    return Key_Val;
}

//Key_Delay函数适用于80MHz,实现一次循环延时1ms;
void Key_Delay(unsigned int ms)
{
    unsigned int i,j;
    for(i=0;i<ms;i++)
        for(j=0;j<8000;j++);
}
复制代码

最后在main函数调用Key_Scan函数即可,这里需要注意按键长按和短按我们赋予其不同的功能,因此逻辑上要做一些判断。

函数入口进来之后,首先读取一个当前的key值,然后再一段时间之后读取新的key'值,这样就能判断出是长按还是短按;

在此基础上,利用par做判断,去分别执行长按和短按的功能。

 

但是如果直接这样思考,会发现LED在按下(一直按着)能实现长按功能,但是一弹起就会跳跃到实现短按功能;所以需要使用一种锁存的想法

将长按信号确定获取之后,就不允许变到短按信号上。

复制代码
void Key_Get(void)
{
    unsigned i;
    Key_Currentval = Key_Scan();
    if(Key_Currentval == 0 || (Key_Currentval == ucLed>>4))
        goto loop;
    Key_Delay(1000);
    Key_Pastval = Key_Scan();
    if((Key_Pastval == Key_Currentval)&&(Key_Pastval!=0))
    {
        par = 1;
    }
    else if(Key_Pastval != Key_Currentval)
        par = 0;
    //按键短按
    if(par==0)
    {
        if(Key_Currentval==1)
            ucLed = 0x01;
        else if(Key_Currentval==2)
            ucLed = 0x02;
        else if(Key_Currentval==4)
            ucLed = 0x04;
        else if(Key_Currentval==8)
            ucLed = 0x08;
    }
    else if(par==1)
    {        
        if(Key_Pastval==1)
            ucLed = 0x10;
        else if(Key_Pastval==2)
            ucLed = 0x20;
        else if(Key_Pastval==4)
            ucLed = 0x40;
        else if(Key_Pastval==8)
            ucLed = 0x80;
    }
    loop:
    {
        i = i;
    }
}
复制代码

//Ps:作为新手,我加入了一些不必要的判断语句,认为这样可以在空闲时占用少一点的cpu资源,不知这样是否合理,欢迎讨论。

END

posted @   charonplus  阅读(474)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示