物联网Lora模块从入门到精通(三)按键的读取与使用

        一、前言

        在Lora例程中,为我们提供了三个按键标志位,我们不需要手动再次初始化按键,即可完成按键的读取。

二、代码实现

        首先,我们一起来阅读hal_key.c中的代码:

/* Includes ------------------------------------------------------------------*/
#include "stm32l1xx_hal.h"
#include "hal_key.h"

char light_status = GPIO_PIN_RESET;
char fan_status = GPIO_PIN_RESET;

void light_ctl_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Pin = LIGHT_CTL_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(LIGHT_CTL_GPIO, &GPIO_InitStruct);

    HAL_GPIO_WritePin(LIGHT_CTL_GPIO, LIGHT_CTL_GPIO_PIN, (GPIO_PinState)light_status);
}

void light_ctl(char is_light_on)
{
    light_status = is_light_on;
    HAL_GPIO_WritePin(LIGHT_CTL_GPIO, LIGHT_CTL_GPIO_PIN, (GPIO_PinState)light_status);
}

void fan_ctl_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Pin = FAN_CTL_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(FAN_CTL_GPIO, &GPIO_InitStruct);

    HAL_GPIO_WritePin(FAN_CTL_GPIO, FAN_CTL_GPIO_PIN, (GPIO_PinState)fan_status);
}

void fan_ctl(char is_fan_on)
{
    fan_status = is_fan_on;
    HAL_GPIO_WritePin(FAN_CTL_GPIO, FAN_CTL_GPIO_PIN, (GPIO_PinState)fan_status);
}

void keys_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Pin = KEY2_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(KEY2_GPIO, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = KEY3_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(KEY3_GPIO, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = KEY4_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(KEY4_GPIO, &GPIO_InitStruct);
}


volatile char is_key2_down = 0;
volatile char is_key3_down = 0;
volatile char is_key4_down = 0;

char isKey2Pressed(void){
	return is_key2_down;
}

char isKey3Pressed(void){
	return is_key3_down;
}

char isKey4Pressed(void){
	return is_key4_down;
}

void resetKey2(void){
	is_key2_down = 0;
}

void resetKey3(void){
	is_key3_down = 0;
}

void resetKey4(void){
	is_key4_down = 0;
}

#define DEBOUNCE_CNT	2
void scan_keys(void)
{
    static char key2_status = KEY_UP, key2_down_cnt = 0, key2_up_cnt = 0;
    static char key3_status = KEY_UP, key3_down_cnt = 0, key3_up_cnt = 0;
    static char key4_status = KEY_UP, key4_down_cnt = 0, key4_up_cnt = 0;
    char new_status;

    //KEY2
    new_status = HAL_GPIO_ReadPin(KEY2_GPIO, KEY2_GPIO_PIN);
    if((key2_status == KEY_UP) && (new_status == KEY_DOWN)) {
        key2_down_cnt++;
        if(key2_down_cnt >= DEBOUNCE_CNT) {
            is_key2_down = 1;
            key2_status = KEY_DOWN;
        }
    } else {
        key2_down_cnt = 0;
    }

    if((key2_status == KEY_DOWN) && (new_status == KEY_UP)) {
        key2_up_cnt++;
        if(key2_up_cnt >= DEBOUNCE_CNT) {
						is_key2_down = 0;
            key2_status = KEY_UP;;
        }
    } else {
        key2_up_cnt = 0;
    }


    //KEY3
    new_status = HAL_GPIO_ReadPin(KEY3_GPIO, KEY3_GPIO_PIN);
    if((key3_status == KEY_UP) && (new_status == KEY_DOWN)) {
        key3_down_cnt++;
        if(key3_down_cnt >= DEBOUNCE_CNT) {
            is_key3_down = 1;
            key3_status = KEY_DOWN;
        }
    } else {
        key3_down_cnt = 0;
    }

    if((key3_status == KEY_DOWN) && (new_status == KEY_UP)) {
        key3_up_cnt++;
        if(key3_up_cnt >= DEBOUNCE_CNT) {
						is_key3_down = 0;
            key3_status = KEY_UP;;
        }
    } else {
        key3_up_cnt = 0;
    }


    //KEY4
    new_status = HAL_GPIO_ReadPin(KEY4_GPIO, KEY4_GPIO_PIN);
    if((key4_status == KEY_UP) && (new_status == KEY_DOWN)) {
        key4_down_cnt++;
        if(key4_down_cnt >= DEBOUNCE_CNT) {
            is_key4_down = 1;
            key4_status = KEY_DOWN;
        }
    } else {
        key4_down_cnt = 0;
    }

    if((key4_status == KEY_DOWN) && (new_status == KEY_UP)) {
        key4_up_cnt++;
        if(key4_up_cnt >= DEBOUNCE_CNT) {
						is_key4_down = 0;
            key4_status = KEY_UP;;
        }
    } else {
        key4_up_cnt = 0;
    }
}

        上述.c文件中,已经为我们初始化了相关引脚,并完成了配置工作。我们使用这个库主要是使用在库中的isKey_Pressed()和resetKey_()函数。

        isKey_Pressed()是在按键被按下后,对应的is_key_down标志位的值发生改变,因此我们读取该标志位的值即可。

        resetKey_()是将其对应的标志位的值重置,这常用在我们已经做完按键的反馈的事件之后进行,以便接受下一次的按键事件。因此,如果我们长时间没有处理按键的事件,标志位反应的仅仅是按过,而并非按下多少次。

        具体使用:

        以上的含义是读取KEY2是否被按下,如果被按下则LED1亮。如果KEY3被按下,则LED1灭。

int main( void )
{
    Init();
    while( 1 )
    {
			if(isKey2Pressed())
			{
				GpioWrite(&Led1,0);
				resetKey2();
			}
			if(isKey3Pressed())
			{
				GpioWrite(&Led1,1);
				resetKey3();
			}
    }
}

        按键进阶:

                双击:

                双击的原理,即在短时间内完成两次点击,即可完成双击操作。因此,代码的核心将放在对本次按下与上一次松开之间的时间的判断。

                长按:

                长按同时也是我们程序开发中,十分重要的一环,通常分为两个部分:按下时与松开后。长按与单击的区别就是按下时间的不同,因此我们需要将代码的核心放到按下的计时上。

        关于单击、双击和长按,推荐大家可以借鉴我的这一篇文章,里边有更详细的表达:

Zigbee单片机开发板-实现单击、双击、长按的识别反馈-超简单方法-新大陆物联网-物联网竞赛-Zigbee&STM32开发板

        这种关于单击、双击与长按的思想不局限与任何芯片,在所有系统中通用。

猜你喜欢

转载自blog.csdn.net/qq_39724355/article/details/131145637
今日推荐