• 正文
    • 一、前言
    • 二、編程講解
    • 三、項(xiàng)目實(shí)戰(zhàn)
    • 四、進(jìn)階學(xué)習(xí)
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

RT-Thread零基礎(chǔ)快速入門(mén)第4講——按鍵輸入

2024/03/26
3042
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

一、前言

上一講我給大家講解了如何點(diǎn)亮一個(gè)LED燈,因?yàn)槭侨腴T(mén)的第一篇,所以講的啰嗦了一點(diǎn),從這一講開(kāi)始,一些最基礎(chǔ)的東西我就不再說(shuō)了,如果有不懂的同學(xué)可以翻一下我之前發(fā)的博客。

這一講我我主要按鍵輸入的原理和編程方法,以及幾種按鍵輸入的進(jìn)階用法。

源碼鏈接

我發(fā)布的所有關(guān)于RT-thread的教程源代碼都在下面這個(gè)鏈接里面,隨著我教程的更新,新的代碼也會(huì)加入進(jìn)去。

教程源碼下載鏈接:https://pan.baidu.com/s/1N2D8dM31deKIqNqaIQfPiA
提取碼:7nsx

二、編程講解

按鍵輸入的電路原理

下圖是我教程所用開(kāi)發(fā)板的按鍵原理圖(我用的是正點(diǎn)原子STM32F4探索者)

在這里插入圖片描述

從圖我們可以看出,KEY_UP按鍵一頭接到電源,一頭接到單片機(jī)IO口,當(dāng)按鍵沒(méi)有按下時(shí),IO口處于懸空的狀態(tài),如果IO口設(shè)置為輸入模式,會(huì)處于低電平狀態(tài),按下之后,IO口接通電源,處于高電平的狀態(tài)。KEY0、KEY1和KEY2則相反。

所以,我們可以通過(guò)判斷IO口的電平即可判斷按鍵是否按下。

按鍵輸入的編程方法

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

通過(guò)rt_pin_mode()函數(shù)可以把按鍵對(duì)應(yīng)的引腳設(shè)置為輸入模式。這個(gè)函數(shù)在上一講也講過(guò)了,這里不再多說(shuō)了。

在這里插入圖片描述

第二步:讀取引腳電平

通過(guò)rt_pin_read() 函數(shù)可以讀取引腳的電平。

在這里插入圖片描述

如果引腳處于高電平,該函數(shù)返回1,如果是低電平,則返回0。

所以我們用一個(gè)if語(yǔ)句判斷rt_pin_read()函數(shù)返回值即可知道引腳電平,從而判斷按鍵是否按下,示例代碼如下:

#define KEY0_PIN    GET_PIN(E, 4)
if (rt_pin_read(KEY0_PIN) == 0)//按鍵按下時(shí)為低電平
{
	 rt_pin_write(LED1_PIN, 0);//點(diǎn)亮LED1
}

三、項(xiàng)目實(shí)戰(zhàn)

按鍵的基本用法

根據(jù)上面的原理,我們寫(xiě)一個(gè)完整的按鍵輸入的示例。

下面的示例代碼運(yùn)行效果:當(dāng)KEY0按下,LED0點(diǎn)亮,松開(kāi)后LED0熄滅;當(dāng)KEY1按下后LED1點(diǎn)亮2秒然后熄滅,當(dāng)KEY_UP按下后,LED1點(diǎn)亮,再按一次,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引腳設(shè)置為輸出 */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    /* 把KEY引腳設(shè)置為輸入 */
    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);

    /* 先把兩個(gè)燈都關(guān)掉 */
    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)//按鍵按下時(shí)為低電平
        {
            rt_thread_mdelay(30);//延時(shí)消抖
            if (rt_pin_read(KEY0_PIN) == PIN_LOW)
            {
                rt_pin_write(LED0_PIN, PIN_LOW);//點(diǎn)亮LED0
            }
        }
        else
        {
            rt_pin_write(LED0_PIN, PIN_HIGH);//熄滅LED0
        }
        
        /* 讀取KEY1引腳電平 */
        if (rt_pin_read(KEY1_PIN) == PIN_LOW)//按鍵按下時(shí)為低電平
        {
            rt_thread_mdelay(30);//延時(shí)消抖
            if (rt_pin_read(KEY1_PIN) == PIN_LOW)
            {
                rt_pin_write(LED1_PIN, PIN_LOW);//點(diǎn)亮LED1
                rt_thread_mdelay(2000);
                rt_pin_write(LED1_PIN, PIN_HIGH);//熄滅LED1
            }
        }

        /* 讀取KEY_UP引腳電平 */
        if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)//按鍵按下時(shí)為高電平
        {
            rt_thread_mdelay(100);//這里延時(shí)時(shí)間長(zhǎng)一點(diǎn),太快的話,按鍵會(huì)多次觸發(fā)
            if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)
            {
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//點(diǎn)亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄滅LED1
                }
            }
        }
    }
}

四、進(jìn)階學(xué)習(xí)

按鍵連按和不連按

連按的意思是一直按住按鍵不放時(shí),按鍵對(duì)應(yīng)的代碼會(huì)循環(huán)執(zhí)行。而不連按則相反,即使按鍵一直按著,按鍵對(duì)應(yīng)的那部分代碼也只會(huì)執(zhí)行一次。

連按和不連按都有各自的用途,沒(méi)有優(yōu)劣之分,比如,我們用的電子手表或者電子鐘,如果支持連按的話,我們?cè)谠O(shè)置時(shí)間的時(shí)候就可以按住讓時(shí)間一直加,如果不支持連按的話,我們就需要連續(xù)按很多次。而用按鍵開(kāi)關(guān)燈的時(shí)候,如果按鍵支持連按,那我們按住的時(shí)候,燈就會(huì)一直閃,所以這個(gè)時(shí)候我們是不希望按鍵支持連按的。

下面的示例代碼運(yùn)行效果:當(dāng)KEY_UP一直按住時(shí),LED1會(huì)一直閃爍,即KEY_UP支持連按。而KEY0和KEY1均不支持連按。

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

    /* 把LED引腳設(shè)置為輸出 */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    /* 把KEY引腳設(shè)置為輸入 */
    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);

    /* 先把兩個(gè)燈都關(guān)掉 */
    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)//按鍵按下時(shí)為高電平
        {
            rt_thread_mdelay(100);//這里延時(shí)時(shí)間長(zhǎng)一點(diǎn),太快的話,按一下會(huì)觸發(fā)幾次
            if (rt_pin_read(KEY_UP_PIN) == PIN_HIGH)
            {
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//點(diǎn)亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄滅LED1
                }
            }
        }

        /* 讀取KEY0引腳電平 */
        if (key_up && rt_pin_read(KEY0_PIN) == PIN_LOW)//按鍵按下時(shí)為低電平
        {
            rt_thread_mdelay(30);//延時(shí)消抖
            key_up = 0;//如果按鍵沒(méi)有松開(kāi),key_up一直為0,就不會(huì)再進(jìn)入這里了
            if (rt_pin_read(KEY0_PIN) == PIN_LOW)
            {
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//點(diǎn)亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄滅LED1
                }
            }
        }
        else if(rt_pin_read(KEY0_PIN) != PIN_LOW)//按鍵松開(kāi)了
        {
            key_up = 1;
        }

        /* 讀取KEY1引腳電平 */
        if (rt_pin_read(KEY1_PIN) == PIN_LOW)//按鍵按下時(shí)為低電平
        {
            rt_thread_mdelay(30);//延時(shí)消抖
            while (rt_pin_read(KEY1_PIN) == PIN_LOW)
            {
                //等待按鍵松開(kāi)
            }
            i = ~i;
            if(i)
            {
                rt_pin_write(LED1_PIN, PIN_LOW);//點(diǎn)亮LED1
            }
            else
            {
                rt_pin_write(LED1_PIN, PIN_HIGH);//熄滅LED1
            }
            
        }
    }
}

按鍵短按和長(zhǎng)按

下面的示例代碼運(yùn)行效果:按鍵KEY0長(zhǎng)按2秒之后,LED1點(diǎn)亮,松開(kāi)后再長(zhǎng)按2秒,LED1熄滅。按鍵KEY0按下不到2秒松開(kāi),LED0點(diǎn)亮,再按一次,LED0熄滅。

/* 按鍵同時(shí)支持長(zhǎng)按和短按 */
int main(void)
{
    int i = 0, j = 0;
    int key_up = 1;
    rt_uint16_t t = 0;

    /* 把LED引腳設(shè)置為輸出 */
    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);

    /* 把KEY引腳設(shè)置為輸入 */
    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);

    /* 先把兩個(gè)燈都關(guān)掉 */
    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)//按鍵按下時(shí)為低電平
        {
            rt_thread_mdelay(10);//延時(shí)消抖
            t++;
            if (t == 200)
            {//長(zhǎng)按兩秒
                j = ~j;
                if(j)
                {
                    rt_pin_write(LED1_PIN, PIN_LOW);//點(diǎn)亮LED1
                }
                else
                {
                    rt_pin_write(LED1_PIN, PIN_HIGH);//熄滅LED1
                }
            }
        }
        else if(rt_pin_read(KEY0_PIN) != PIN_LOW)//按鍵松開(kāi)
        {
            if(t >=3 && t<= 200)
            {//短按
                i = ~i;
                if(i)
                {
                    rt_pin_write(LED0_PIN, PIN_LOW);//點(diǎn)亮LED0
                }
                else
                {
                    rt_pin_write(LED0_PIN, PIN_HIGH);//熄滅LED0
                }    
            }
            t = 0;
        }
    }
}

五、結(jié)束語(yǔ)

好了,關(guān)于按鍵輸入的編程講解就到這里,如果還有什么問(wèn)題可以私信給我。如果需要本文對(duì)應(yīng)的源碼的話可以在博文前言部分的鏈接下載。

如果覺(jué)得這篇文章對(duì)你有用,可以賞個(gè)贊給博主。

后續(xù)我會(huì)繼續(xù)更新RT-thread入門(mén)教程系列,如果感興趣的同學(xué)可以關(guān)注一下博主,謝謝!

RT-thread相關(guān)教程匯總:https://blog.csdn.net/ShenZhen_zixian/article/details/120563891

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
DS2433S 1 Dallas Semiconductor EEPROM, 512X8, Serial, CMOS, PDSO8,
暫無(wú)數(shù)據(jù) 查看
KSZ8873RLLI 1 Microchip Technology Inc DATACOM, LAN SWITCHING CIRCUIT, PQFP64
$6.1 查看
HCPL-181-00BE 1 Avago Technologies 1 CHANNEL TRANSISTOR OUTPUT OPTOCOUPLER, ROHS COMPLIANT, MINIFLAT, SMD, SOP-4

ECAD模型

下載ECAD模型
$0.86 查看

相關(guān)推薦

  • 以RT-Thread 為例,分享一下我的學(xué)習(xí)方法
  • 玩轉(zhuǎn)RT-Thread之消息隊(duì)列的應(yīng)用
    文章
    1815
    2024/07/23
  • RT-Thread零基礎(chǔ)快速入門(mén)第9講——串口(UART/RS485)
    文章
    6856
    2024/07/11
  • RT-thread應(yīng)用講解——OTA
    文章
    4092
    2024/07/10