[单片机框架][bsp层][AT32F415][bsp_key] 按键KEY配置和使用

发布者:会哭的蓝精灵最新更新时间:2022-09-26 来源: csdn 手机看文章 扫描二维码
随时随地手机看文章

按键的基本原理是设置单片机IO口(PB0-PB3)为输入状态,如DDRB = 0XF0(方向寄存器,“1”为输出,“0”为输入);


单片机一直检测按键端口(PB0-PB3)的状态,当端口为低电平时(即按键按下),实行相应的动作(比如控制LED灯)。


原理就是这么回事,但是正真实现时,按键会有抖动,要进行按键去抖,下图为按键按下时的抖动图。


按键实行一个动作过程是需要一定时间的,一般为100mS-1S左右,而一个单片机执行一个机器周期的时间很短,时钟为10MH的周期为0.1μs,这样按键每一次动作程序就会多次检测按键,出现误判(一次按下,多次动作)。


代码将讲解如何实现按键扫描功能,注册按键事件(单击/双击/长按/长长按/按下/松开)

/********************************************************************************

* @file    bsp_key.c

* @author  jianqiang.xue

* @version V1.0.0

* @date    2021-10-10

* @brief   NULL

********************************************************************************/


/* Includes ------------------------------------------------------------------*/

#include

#include

#include


#include "RTE_Components.h"

#include CMSIS_device_header


#include "bsp_gpio.h"

#include "bsp_exti.h"

#include "bsp_led.h"

#include "bsp_key.h"


/* Private Includes ----------------------------------------------------------*/

#include "business_gpio.h"

#include "business_function.h"


/* Private Define ------------------------------------------------------------*/


/* Private Variables ---------------------------------------------------------*/

#if (BS_BUTTON_NUM != 0)

static const bsp_gpio_t g_gpio_init[BS_BUTTON_NUM] =

{

#if (BS_BUTTON_NUM > 0)

    {BS_BUTTON0_GPIO_PORT, BS_BUTTON0_PIN, BS_BUTTON0_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON0_PULL, BS_BUTTON0_EXTI_SEL, BS_BUTTON0_EXTI_IRQn, BS_BUTTON0_EXTI_EDGE_LEVEL_SEL, BS_BUTTON0_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 1)

    {BS_BUTTON1_GPIO_PORT, BS_BUTTON1_PIN, BS_BUTTON1_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON1_PULL, BS_BUTTON1_EXTI_SEL, BS_BUTTON1_EXTI_IRQn, BS_BUTTON1_EXTI_EDGE_LEVEL_SEL, BS_BUTTON1_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 2)

    {BS_BUTTON2_GPIO_PORT, BS_BUTTON2_PIN, BS_BUTTON2_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON2_PULL, BS_BUTTON2_EXTI_SEL, BS_BUTTON2_EXTI_IRQn, BS_BUTTON2_EXTI_EDGE_LEVEL_SEL, BS_BUTTON2_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 3)

    {BS_BUTTON3_GPIO_PORT, BS_BUTTON3_PIN, BS_BUTTON3_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON3_PULL, BS_BUTTON3_EXTI_SEL, BS_BUTTON3_EXTI_IRQn, BS_BUTTON3_EXTI_EDGE_LEVEL_SEL, BS_BUTTON3_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 4)

    {BS_BUTTON4_GPIO_PORT, BS_BUTTON4_PIN, BS_BUTTON4_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON4_PULL, BS_BUTTON4_EXTI_SEL, BS_BUTTON4_EXTI_IRQn, BS_BUTTON4_EXTI_EDGE_LEVEL_SEL, BS_BUTTON4_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 5)

    {BS_BUTTON5_GPIO_PORT, BS_BUTTON5_PIN, BS_BUTTON5_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON5_PULL, BS_BUTTON5_EXTI_SEL, BS_BUTTON5_EXTI_IRQn, BS_BUTTON5_EXTI_EDGE_LEVEL_SEL, BS_BUTTON5_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 6)

    {BS_BUTTON6_GPIO_PORT, BS_BUTTON6_PIN, BS_BUTTON6_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON6_PULL, BS_BUTTON6_EXTI_SEL, BS_BUTTON6_EXTI_IRQn, BS_BUTTON6_EXTI_EDGE_LEVEL_SEL, BS_BUTTON6_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 7)

    {BS_BUTTON7_GPIO_PORT, BS_BUTTON7_PIN, BS_BUTTON7_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON7_PULL, BS_BUTTON7_EXTI_SEL, BS_BUTTON7_EXTI_IRQn, BS_BUTTON7_EXTI_EDGE_LEVEL_SEL, BS_BUTTON7_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 8)

    {BS_BUTTON8_GPIO_PORT, BS_BUTTON8_PIN, BS_BUTTON8_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON8_PULL, BS_BUTTON8_EXTI_SEL, BS_BUTTON8_EXTI_IRQn, BS_BUTTON8_EXTI_EDGE_LEVEL_SEL, BS_BUTTON8_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 9)

    {BS_BUTTON9_GPIO_PORT, BS_BUTTON9_PIN, BS_BUTTON9_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON9_PULL, BS_BUTTON9_EXTI_SEL, BS_BUTTON9_EXTI_IRQn, BS_BUTTON9_EXTI_EDGE_LEVEL_SEL, BS_BUTTON9_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 10)

    {BS_BUTTON10_GPIO_PORT, BS_BUTTON10_PIN, BS_BUTTON10_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON10_PULL, BS_BUTTON10_EXTI_SEL, BS_BUTTON10_EXTI_IRQn, BS_BUTTON10_EXTI_EDGE_LEVEL_SEL, BS_BUTTON10_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 11)

    {BS_BUTTON11_GPIO_PORT, BS_BUTTON11_PIN, BS_BUTTON11_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON11_PULL, BS_BUTTON11_EXTI_SEL, BS_BUTTON11_EXTI_IRQn, BS_BUTTON11_EXTI_EDGE_LEVEL_SEL, BS_BUTTON11_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 12)

    {BS_BUTTON12_GPIO_PORT, BS_BUTTON12_PIN, BS_BUTTON12_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON12_PULL, BS_BUTTON12_EXTI_SEL, BS_BUTTON12_EXTI_IRQn, BS_BUTTON12_EXTI_EDGE_LEVEL_SEL, BS_BUTTON12_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 13)

    {BS_BUTTON13_GPIO_PORT, BS_BUTTON13_PIN, BS_BUTTON13_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON13_PULL, BS_BUTTON13_EXTI_SEL, BS_BUTTON13_EXTI_IRQn, BS_BUTTON13_EXTI_EDGE_LEVEL_SEL, BS_BUTTON13_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 14)

    {BS_BUTTON14_GPIO_PORT, BS_BUTTON14_PIN, BS_BUTTON14_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON14_PULL, BS_BUTTON14_EXTI_SEL, BS_BUTTON14_EXTI_IRQn, BS_BUTTON14_EXTI_EDGE_LEVEL_SEL, BS_BUTTON14_EXTI_RISE_FALL_SEL},

#endif

#if (BS_BUTTON_NUM > 15)

    {BS_BUTTON15_GPIO_PORT, BS_BUTTON15_PIN, BS_BUTTON15_GPIO_CLK, BSP_GPIO_PIN_SET, BS_BUTTON15_PULL, BS_BUTTON15_EXTI_SEL, BS_BUTTON15_EXTI_IRQn, BS_BUTTON15_EXTI_EDGE_LEVEL_SEL, BS_BUTTON15_EXTI_RISE_FALL_SEL},

#endif

};


/* External Variables --------------------------------------------------------*/

typedef void(*bsp_button_callback)(void);

static bsp_button_callback irq_callback[BS_BUTTON_NUM] = {0};

/* Private Macro -------------------------------------------------------------*/

static void bsp_button_exti_callback(void *gpiox, uint16_t gpio_pin);

/* Public Function Prototypes -----------------------------------------------*/


/**

 * @brief  [初始化] 按键引脚初始化并注册按键外部中断回调函数

 */

void bsp_button_init(void)

{

    uint8_t ch;


    for (ch = 0; ch < BS_BUTTON_NUM; ch++)

    {

        /* Enable the BUTTON Clock */

        bsp_gpio_set_clk(GPIO_APBx, g_gpio_init[ch].periph, true);


        if (g_gpio_init[ch].is_exti == DISABLE)

        {

            /* Configure Button pin as input */

            bsp_gpio_init_input(g_gpio_init[ch].port, g_gpio_init[ch].pin, g_gpio_init[ch].pull);

        }

        else

        {

            /* Configure Button pin as input with External interrupt */

            irq_callback[ch] = NULL;

            bsp_gpio_init_input_exit(g_gpio_init[ch].port, g_gpio_init[ch].pin, g_gpio_init[ch].irqn,

                                     g_gpio_init[ch].exti_type,

                                     g_gpio_init[ch].exti_event,

                                     g_gpio_init[ch].pull);

        }

    }


    if (BS_BUTTON_NUM)

    {

        bsp_gpio_exit_irq_register_callback(bsp_button_exti_callback);

    }

}


/**

 * @brief  [反初始化] 按键恢复默认状态

 * @param  ch: 按键号

 */

void bsp_button_deinit(bsp_button_t ch)

{

    bsp_gpio_deinit(g_gpio_init[ch].port, g_gpio_init[ch].pin);

}


/**

 * @brief  设置按键中断优先级(强制配置为低优先级)

 * @param  ch: 按键号

 */

void bsp_button_set_irq(bsp_button_t ch)

{

    bsp_exit_set(g_gpio_init[ch].irqn, 3);

}


/**

 * @brief  清除按键中断优先级

 * @param  ch: 按键号

 */

void bsp_button_clear_irq(bsp_button_t ch)

{

    bsp_exit_clear_set(g_gpio_init[ch].irqn);

}


/**

 * @brief  得到按键状态

 * @param  ch: 按键号

 * @retval 0 -- 低电平, 1 -- 高电平

 */

bool bsp_button_get_state(bsp_button_t ch)

{

    return (bool)bsp_gpio_get_state(g_gpio_init[ch].port, g_gpio_init[ch].pin);

}


/**

 * @brief  注册按键中断的回调函数

 * @param  ch: 键号

 * @param  event: 绑定中断回调事件

 * @retval 0--失败  1--成功

 */

bool bsp_button_irq_callback(bsp_button_t ch, void *event)

{

    if (irq_callback[ch] != NULL)

    {

        return false;

    }

    else

    {

        irq_callback[ch] = (bsp_button_callback)event;

    }

    return true;

}


/**

 * @brief  用于外部中断服务回调,并执行对应引脚的事件

 * @param  gpiox: -

 * @param  gpio_pin: 引脚号

 */

static void bsp_button_exti_callback(void *gpiox, uint16_t gpio_pin)

{

#if BS_BUTTON_NUM > 0

    if (gpio_pin == BS_BUTTON0_PIN && irq_callback[BSP_BUTTON_X_0] != NULL)

    {

        if (irq_callback[BSP_BUTTON_X_0])

        {

            irq_callback[BSP_BUTTON_X_0]();

        }

    }

#endif

#if BS_BUTTON_NUM > 1

    else if (gpio_pin == BS_BUTTON1_PIN && irq_callback[BSP_BUTTON_X_1] != NULL)

    {

        if (irq_callback[BSP_BUTTON_X_1])

        {

            irq_callback[BSP_BUTTON_X_1]();

        }

    }

#endif

#if BS_BUTTON_NUM > 2

    else if (gpio_pin == BS_BUTTON2_PIN && irq_callback[BSP_BUTTON_X_2] != NULL)

    {

        if (irq_callback[BSP_BUTTON_X_2])

        {

            irq_callback[BSP_BUTTON_X_2]();

        }

    }

#endif

#if BS_BUTTON_NUM > 3

    else if (gpio_pin == BS_BUTTON3_PIN && irq_callback[BSP_BUTTON_X_3] != NULL)

[1] [2]
引用地址:[单片机框架][bsp层][AT32F415][bsp_key] 按键KEY配置和使用

上一篇:[单片机框架][bsp层][AT32F415][bsp_adc] adc配置和使用
下一篇:[单片机框架][bsp层][AT32F415][bsp_led] LED配置和使用

推荐阅读最新更新时间:2024-11-12 09:44

[bsp][nrf52832][nrf52840][nrf52810][nrf52820][bsp_adc] ADC/SSADC配置和使用
SAADC -逐次逼近模拟-数字转换器 ADC是一种差分逐次逼近寄存器(SAR)模数转换器。 以下是SAADC的主要特点: 8/10/12位分辨率,带过采样的14位分辨率 多达8个输入通道 单端输入一个通道,差分输入两个通道 扫描模式可以配置单端通道和差分通道。 满量程输入范围(0到VDD) 通过软件或PPI通道的任务触发采样,以充分灵活的采样频率源,从低功耗32.768kHz RTC或更准确的1/16MHz定时器 一次性转换模式,采样单通道 扫描模式,按顺序采样一系列通道。 信道之间的采样延迟是tack + tconv,根据用户的tack配置,信道之间的延迟会有所不同。 •支持使用EasyDMA直接将样品传输到RAM 在单个
[单片机]
[<font color='red'>bsp</font><font color='red'>层</font>][nrf52832][nrf52840][nrf52810][nrf52820][<font color='red'>bsp</font>_adc] ADC/SSADC<font color='red'>配置</font>和使用
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved