加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 一、前言
    • 二、编程讲解
    • 三、项目实战
    • 四、进阶学习
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

RT-Thread零基础快速入门第4讲——按键输入

03/26 07:53
927
阅读需 16 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

一、前言

上一讲我给大家讲解了如何点亮一个LED灯,因为是入门的第一篇,所以讲的啰嗦了一点,从这一讲开始,一些最基础的东西我就不再说了,如果有不懂的同学可以翻一下我之前发的博客。

这一讲我我主要按键输入的原理和编程方法,以及几种按键输入的进阶用法。

源码链接

我发布的所有关于RT-thread的教程源代码都在下面这个链接里面,随着我教程的更新,新的代码也会加入进去。

教程源码下载链接:https://pan.baidu.com/s/1N2D8dM31deKIqNqaIQfPiA
提取码:7nsx

二、编程讲解

按键输入的电路原理

下图是我教程所用开发板的按键原理图(我用的是正点原子STM32F4探索者)

在这里插入图片描述

从图我们可以看出,KEY_UP按键一头接到电源,一头接到单片机IO口,当按键没有按下时,IO口处于悬空的状态,如果IO口设置为输入模式,会处于低电平状态,按下之后,IO口接通电源,处于高电平的状态。KEY0、KEY1和KEY2则相反。

所以,我们可以通过判断IO口的电平即可判断按键是否按下。

按键输入的编程方法

第一步:把IO配置成输入模式

通过rt_pin_mode()函数可以把按键对应的引脚设置为输入模式。这个函数在上一讲也讲过了,这里不再多说了。

在这里插入图片描述

第二步:读取引脚电平

通过rt_pin_read() 函数可以读取引脚的电平。

在这里插入图片描述

如果引脚处于高电平,该函数返回1,如果是低电平,则返回0。

所以我们用一个if语句判断rt_pin_read()函数返回值即可知道引脚电平,从而判断按键是否按下,示例代码如下:

#define KEY0_PIN    GET_PIN(E, 4)
if (rt_pin_read(KEY0_PIN) == 0)//按键按下时为低电平
{
	 rt_pin_write(LED1_PIN, 0);//点亮LED1
}

三、项目实战

按键的基本用法

根据上面的原理,我们写一个完整的按键输入的示例。

下面的示例代码运行效果:当KEY0按下,LED0点亮,松开后LED0熄灭;当KEY1按下后LED1点亮2秒然后熄灭,当KEY_UP按下后,LED1点亮,再按一次,LED1熄灭。

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define LED0_PIN    GET_PIN(F, 9)
#define LED1_PIN    GET_PIN(F, 10)
#define KEY0_PIN    GET_PIN(E, 4)
#define KEY1_PIN    GET_PIN(E, 3)
#define KEY2_PIN    GET_PIN(E, 2)
#define KEY_UP_PIN  GET_PIN(A, 0)

/* 按键输入基本用法 */
int main(void)
{
    int i = 0;

    /* 把LED引脚设置为输出 */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    /* 把KEY引脚设置为输入 */
    rt_pin_mode(KEY0_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY_UP_PIN, PIN_MODE_INPUT);

    /* 先把两个灯都关掉 */
    rt_pin_write(LED0_PIN, PIN_HIGH);
    rt_pin_write(LED1_PIN, PIN_HIGH);

    while (1)
    {
        /* 读取KEY0引脚电平 */
        if (rt_pin_read(KEY0_PIN) == PIN_LOW)//按键按下时为低电平
        {
            rt_thread_mdelay(30);//延时消抖
            if (rt_pin_read(KEY0_PIN) == PIN_LOW)
            {
                rt_pin_write(LED0_PIN, PIN_LOW);//点亮LED0
            }
        }
        else
        {
            rt_pin_write(LED0_PIN, PIN_HIGH);//熄灭LED0
        }
        
        /* 读取KEY1引脚电平 */
        if (rt_pin_read(KEY1_PIN) == PIN_LOW)//按键按下时为低电平
        {
            rt_thread_mdelay(30);//延时消抖
            if (rt_pin_read(KEY1_PIN) == PIN_LOW)
            {
                rt_pin_write(LED1_PIN, PIN_LOW);//点亮LED1
                rt_thread_mdelay(2000);
                rt_pin_write(LED1_PIN, PIN_HIGH);//熄灭LED1
            }
        }

        /* 读取KEY_UP引脚电平 */
        if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)//按键按下时为高电平
        {
            rt_thread_mdelay(100);//这里延时时间长一点,太快的话,按键会多次触发
            if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)
            {
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//点亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄灭LED1
                }
            }
        }
    }
}

四、进阶学习

按键连按和不连按

连按的意思是一直按住按键不放时,按键对应的代码会循环执行。而不连按则相反,即使按键一直按着,按键对应的那部分代码也只会执行一次。

连按和不连按都有各自的用途,没有优劣之分,比如,我们用的电子手表或者电子钟,如果支持连按的话,我们在设置时间的时候就可以按住让时间一直加,如果不支持连按的话,我们就需要连续按很多次。而用按键开关灯的时候,如果按键支持连按,那我们按住的时候,灯就会一直闪,所以这个时候我们是不希望按键支持连按的。

下面的示例代码运行效果:当KEY_UP一直按住时,LED1会一直闪烁,即KEY_UP支持连按。而KEY0和KEY1均不支持连按。

/* 按键支持连按和不支持连按 */
int main(void)
{
    int i = 0;
    int key_up = 1;

    /* 把LED引脚设置为输出 */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    /* 把KEY引脚设置为输入 */
    rt_pin_mode(KEY0_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY_UP_PIN, PIN_MODE_INPUT);

    /* 先把两个灯都关掉 */
    rt_pin_write(LED0_PIN, PIN_HIGH);
    rt_pin_write(LED1_PIN, PIN_HIGH);

    while (1)
    {
        /* 读取KEY_UP引脚电平 */
        if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)//按键按下时为高电平
        {
            rt_thread_mdelay(100);//这里延时时间长一点,太快的话,按一下会触发几次
            if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)
            {
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//点亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄灭LED1
                }
            }
        }

        /* 读取KEY0引脚电平 */
        if (key_up && rt_pin_read(KEY0_PIN) == PIN_LOW)//按键按下时为低电平
        {
            rt_thread_mdelay(30);//延时消抖
            key_up = 0;//如果按键没有松开,key_up一直为0,就不会再进入这里了
            if (rt_pin_read(KEY0_PIN) == PIN_LOW)
            {
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//点亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄灭LED1
                }
            }
        }
        else if(rt_pin_read(KEY0_PIN) != PIN_LOW)//按键松开了
        {
            key_up = 1;
        }

        /* 读取KEY1引脚电平 */
        if (rt_pin_read(KEY1_PIN) == PIN_LOW)//按键按下时为低电平
        {
            rt_thread_mdelay(30);//延时消抖
            while (rt_pin_read(KEY1_PIN) == PIN_LOW)
            {
                //等待按键松开
            }
            i = ~i;
            if(i)
            {
                rt_pin_write(LED1_PIN, PIN_LOW);//点亮LED1
            }
            else
            {
                rt_pin_write(LED1_PIN, PIN_HIGH);//熄灭LED1
            }
            
        }
    }
}

按键短按和长按

下面的示例代码运行效果:按键KEY0长按2秒之后,LED1点亮,松开后再长按2秒,LED1熄灭。按键KEY0按下不到2秒松开,LED0点亮,再按一次,LED0熄灭。

/* 按键同时支持长按和短按 */
int main(void)
{
    int i = 0, j = 0;
    int key_up = 1;
    rt_uint16_t t = 0;

    /* 把LED引脚设置为输出 */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    /* 把KEY引脚设置为输入 */
    rt_pin_mode(KEY0_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT);
    rt_pin_mode(KEY_UP_PIN, PIN_MODE_INPUT);

    /* 先把两个灯都关掉 */
    rt_pin_write(LED0_PIN, PIN_HIGH);
    rt_pin_write(LED1_PIN, PIN_HIGH);

    while (1)
    {
        /* 读取KEY0引脚电平 */
        if (rt_pin_read(KEY0_PIN) == PIN_LOW)//按键按下时为低电平
        {
            rt_thread_mdelay(10);//延时消抖
            t++;
            if (t == 200)
            {//长按两秒
                j = ~j;
                if(j)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//点亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄灭LED1
                }
            }
        }
        else if(rt_pin_read(KEY0_PIN) != PIN_LOW)//按键松开
        {
            if(t >=3 && t<= 200)
            {//短按
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED0_PIN, PIN_LOW);//点亮LED0
                }
                else
                {
                    rt_pin_write(LED0_PIN, PIN_HIGH);//熄灭LED0
                }    
            }
            t = 0;
        }
    }
}

五、结束语

好了,关于按键输入的编程讲解就到这里,如果还有什么问题可以私信给我。如果需要本文对应的源码的话可以在博文前言部分的链接下载。

如果觉得这篇文章对你有用,可以赏个赞给博主。

后续我会继续更新RT-thread入门教程系列,如果感兴趣的同学可以关注一下博主,谢谢!

RT-thread相关教程汇总:https://blog.csdn.net/ShenZhen_zixian/article/details/120563891

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
PLR135/T 1 Everlight Electronics Co Ltd Receiver, 16Mbps, Surface Mount,
$1.8 查看
KSZ8999I 1 Microchip Technology Inc DATACOM, LAN SWITCHING CIRCUIT, PQFP208

ECAD模型

下载ECAD模型
$31.28 查看
AFBR-5921ALZ 1 Agilent Technologies Inc Fiber Optic Device
$32.4 查看

相关推荐

电子产业图谱