STM32
直播中

一说就是错

12年用户 532经验值
私信 关注
[问答]

STM32单片机是如何实现按键控制LED灯设计的

STM32单片机是如何实现按键控制LED灯设计的?求大神解答

回帖(1)

刘敏

2021-11-25 10:11:28
工程项目结构:
其中画红色方框部分为主要函数实现功能




key.h



#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#include "DELAY/Delay.h"

/*
        keyval = 0000 0000
        KEY_UP = 0000 0001
        KEY_DOWN = 0000 0010
        KEY_ALL = 0000 0011
*/
typedef enum
{
    KEY_NO = 0x00,   //没有按键按下
    KEY_UP = 0x01,   //UP键按下
    KEY_DOWN = 0x02, //DOWN键按下
    KEY_ALL = 0x03   //同时按下
}KEY_VALUE;

typedef enum
{
    KEY_PRESS = 0x01,  //按下按键
    KEY_RELEASE = 0x02 //释放按键
}KEY_MODE;

#define KEY_UP_PIN    GPIO_Pin_3 //宏定义KEYUP引脚
#define KEY_DOWN_PIN  GPIO_Pin_4 //宏定义KEYDWON引脚

void initKey(void);
u8 getKeyValue(u8 mode);

#endif
key.c


#include "KEY/key.h"

/**
* 功能:初始化按键
* 参数:None
* 返回值:None
*/
void initKey(void)
{
        GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); //使能GPIO时钟

    GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN|KEY_DOWN_PIN;                  //设置按键对应引脚 UP->PE3, DOWN->PE4
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //设置上拉输入
        GPIO_Init(GPIOE, &GPIO_InitStructure);                          //设置生效
}

/**
* 功能:获取按键值,支持同时按下,按键释放后生效
* 参数:mode:用于指定按键触发方式,参数可选:KEY_PRESS,KEY_RELEASE
* 返回值:返回按键值,当同时按下时,返回值是 KEY_UP|KEY_DOWN 即0x03
*/
u8 getKeyValue(u8 mode)
{
    u8 keyval = 0;

       
        // 不改变其它位的情况下只对某一位置用 | 运算
        // 不改变其它位的情况下只对某一位清零用 & 运算
    if(mode == KEY_PRESS) //按下按键即可生效
    {
         /**************检测UP键函数段********************/
        if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第一次检测时按下
        {
            Delay_ms(10); //延时去抖
            if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第二次检测还为零则可以确定按键按下
            {
                keyval |= KEY_UP;
            }else
            {
                keyval &= ~KEY_UP;
            }
        }else
        {
            keyval &= ~KEY_UP;  //没有按下 对应位清零
        }

        /**************检测DOWN键函数段********************/
        if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第一次检测时按下
        {
            Delay_ms(10); //延时去抖
            if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第二次检测还为零则可以确定按键按下
            {
                keyval |= KEY_DOWN;
            }else
            {
                keyval &= ~KEY_DOWN;
            }
        }else
        {
            keyval &= ~KEY_DOWN;  //没有按下 对应位清零
        }
    }else if(mode == KEY_RELEASE) //松开按键生效
    {
         /**************检测UP键函数段********************/
        if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第一次检测时按下
        {
            Delay_ms(10); //延时去抖
            if(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0) //第二次检测还为零则可以确定按键按下
            {
                keyval |= KEY_UP;
            }else
            {
                keyval &= ~KEY_UP;
            }
        }else
        {
            keyval &= ~KEY_UP;  //没有按下 对应位清零
        }

        /**************检测DOWN键函数段********************/
        if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第一次检测时按下
        {
            Delay_ms(10); //延时去抖
            if(GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0) //第二次检测还为零则可以确定按键按下
            {
                keyval |= KEY_DOWN;
            }else
            {
                keyval &= ~KEY_DOWN;
            }
        }else
        {
            keyval &= ~KEY_DOWN;  //没有按下 对应位清零
        }

        while(GPIO_ReadInputDataBit(GPIOE,KEY_UP_PIN)==0 || GPIO_ReadInputDataBit(GPIOE,KEY_DOWN_PIN)==0); //等待按键释放
    }

    return keyval;
}
main.c


#include "LED/LED.h"
#include "stm32f10x.h"
#include "DELAY/Delay.h"
#include "KEY/key.h"

int main(void)
{
        u16 time = 500; //LED闪烁时间 开机默认500ms
        u8 keyvalue;
       
        initSysTick(); //初始化Systick
        initLED();            //初始化LED       
        initKey();     //初始化按键
        while (1)
        {
                keyvalue= getKeyValue(KEY_PRESS); //获取键值
                switch(keyvalue)
                {
                        case KEY_UP:         time = 50;                        break;//50ms频率闪烁
                        case KEY_DOWN:        time = 2000;                break;//2s频率闪烁
                        case KEY_ALL: blinkLED(10,50,500); break;//同时按下时,亮50ms灭500ms闪烁10次

                        default:                                                        break;//没按下不做任何处理
                }
                blinkLED(1,time,time);
        }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分