RT-Thread Studio使用轮询法检测按键

RT-Thread Studio使用轮询法检测按键

在之前创建的Hello World项目中添加按键检测功能

一、创建一个新的线程用于按键检测

1、使用动态线程创建方法创建一个线程
首先,定义一个动态线程句柄结构体指针:

/* 定义一个按键检测线程句柄结构体指针 */
static rt_thread_t key_thread = RT_NULL;

然后使用动态线程创建函数创建一个线程,其中线程优先级的范围根据系统配置情况不同,可以在rtconfig.h中查看 RT_THREAD_PRIORITY_MAX 宏定义

/* 创建按键检测线程*/
key_thread = rt_thread_create(  "key thread",       /* 线程的名称 */
                                key_thread_entry,   /* 线程入口函数 */
                                RT_NULL,            /* 线程入口函数的参数   */
                                256,                /* 线程栈大小,单位是字节  */
                                5,                  /* 线程的优先级,数值越小优先级越高*/
                                10);                /* 线程的时间片大小 */

线程创建成功后会返回该创建成功的线程句柄,如果线程创建失败,则返回RT_NULL,当线程创建成功后,我们启动该线程,让该线程进入就绪态

/* 如果获得线程控制块,启动这个线程 */
if (key_thread != RT_NULL)
    rt_err = rt_thread_startup(key_thread);
else
    rt_kprintf("key thread create failure !!! \n");

/* 判断线程是否启动成功 */
if( rt_err == RT_EOK)
    rt_kprintf("key thread startup ok. \n");
else
    rt_kprintf("key thread startup err. \n");

2、使用静态线程创建方法创建一个线程
静态线程创建需要提供线程栈和句柄:

/*定义一个按键检测静态线程栈*/
static char key_thread_stack[256];
/*定义一个按键检测静态线程句柄*/
static struct rt_thread key_thread;

然后使用静态线程初始化函数初始化静态线程对象

	/* 初始化按键检测线程,名称是thread2,入口是thread2_entry */
    rt_err = rt_thread_init(&key_thread,                /* 线程句柄 */        
                           "key thread",                /* 线程的名称 */
                           key_thread_entry,            /* 线程入口函数 */
                           RT_NULL,                     /* 线程入口函数的参数   */
                           &key_thread_stack[0],        /* 线程栈起始地址*/
                           sizeof(key_thread_stack),    /* 线程栈大小,单位是字节*/
                           5,                           /* 线程的优先级,数值越小优先级越高*/
                           10);                         /* 线程的时间片大小 */

线程创建成功后返回值为RT_EOK,创建失败则返回-RT_ERROR,当线程创建成功后,我们启动该线程,让该线程进入就绪态

	/* 如果线程创建成功,启动这个线程 */
    if (rt_err == RT_EOK)
        rt_err = rt_thread_startup(&key_thread);
    else
        rt_kprintf("key thread init failure !!! \n");

    /* 判断线程是否启动成功 */
    if( rt_err == RT_EOK)
        rt_kprintf("key thread startup ok. \n");
    else
        rt_kprintf("key thread startup err. \n");

二、编写线程入口函数

首先,我们需要获取按键对应的引脚编号,使用 GET_PIN 宏定义,查看原理图,获取按键对应的引脚
在这里插入图片描述

/* 获取相应的引脚编号 */
#define PIN_WK_UP   GET_PIN(C, 13)
#define PIN_KEY0    GET_PIN(D, 10)
#define PIN_KEY1    GET_PIN(D, 9)
#define PIN_KEY2    GET_PIN(D, 8)

接下来,我们编写一下按键检测线程入口函数,因为硬件上已经有上下拉了,所以就不配置内部上下拉了

/* 按键检测线程入口函数*/
static void key_thread_entry(void *parameter)
{
    static rt_uint8_t key_up = 1;   /* 按键松开标志 */
    /* 初始化按键 */
    rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT);
    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);
    rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT);
    rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT);

    while (1)
    {
        /* 检测按键是否按下 */
        if (key_up && ((rt_pin_read(PIN_WK_UP) == PIN_HIGH) ||
                      (rt_pin_read(PIN_KEY0) == PIN_LOW)    ||
                      (rt_pin_read(PIN_KEY1) == PIN_LOW)    ||
                      (rt_pin_read(PIN_KEY2) == PIN_LOW) )       )
        {
            rt_thread_mdelay(50);   /* 延时消抖*/
            key_up = 0;
            if (rt_pin_read(PIN_WK_UP) == PIN_HIGH)
            {
                /* 按键WK_UP按下,按键按下处理*/
                rt_kprintf("WK_UP pressed!\n");
            }
            else if (rt_pin_read(PIN_KEY0) == PIN_LOW)
            {
                /* 按键KEY0按下,按键按下处理*/
                rt_kprintf("KEY0 pressed!\n");
            }
            else if (rt_pin_read(PIN_KEY1) == PIN_LOW)
            {
                /* 按键KEY0按下,按键按下处理*/
                rt_kprintf("KEY1 pressed!\n");
            }
            else if (rt_pin_read(PIN_KEY2) == PIN_LOW)
            {
                /* 按键KEY0按下,按键按下处理*/
                rt_kprintf("KEY2 pressed!\n");
            }
        }
        else if((rt_pin_read(PIN_WK_UP) == PIN_LOW) &&
                (rt_pin_read(PIN_KEY0) == PIN_HIGH) &&
                (rt_pin_read(PIN_KEY1) == PIN_HIGH) &&
                (rt_pin_read(PIN_KEY2) == PIN_HIGH)     )
        {
            key_up = 1;     /* 按键已松开 */
        }
        rt_thread_mdelay(100);
    }

}

三、实现效果

构建并下载程序,查看串口终端输出:
在这里插入图片描述
可以看到,按键检测线程启动成功,按键功能也实现了

四、代码优化

上面我们的代码都写在了mian.c里,我们可以将其放在一个单独的app_key.c文件中
右键选中【applications】,选择新建源文件
在这里插入图片描述
输入 app_key.c文件名,点击确定:
在这里插入图片描述
将之前编写的代码都迁移到该文件中来,并提供一个app_key_init()函数供main()函数调用

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

/* 使用静态方法线程创建*/
#define STATIC_METHON

#ifndef STATIC_METHON
/* 定义一个按键检测线程句柄结构体指针 */
static rt_thread_t key_thread = RT_NULL;
#else
/*定义一个按键检测静态线程栈*/
static char key_thread_stack[256];
/*定义一个按键检测静态线程句柄*/
static struct rt_thread key_thread;
#endif

/* 获取相应的引脚编号 */
#define PIN_WK_UP   GET_PIN(C, 13)
#define PIN_KEY0    GET_PIN(D, 10)
#define PIN_KEY1    GET_PIN(D, 9)
#define PIN_KEY2    GET_PIN(D, 8)

/* 按键检测线程入口函数*/
static void key_thread_entry(void *parameter)
{
    static rt_uint8_t key_up = 1;   /* 按键松开标志 */
    /* 初始化按键 */
    rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT);
    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);
    rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT);
    rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT);

    while (1)
    {
        /* 检测按键是否按下 */
        if (key_up && ((rt_pin_read(PIN_WK_UP) == PIN_HIGH) ||
                      (rt_pin_read(PIN_KEY0) == PIN_LOW)    ||
                      (rt_pin_read(PIN_KEY1) == PIN_LOW)    ||
                      (rt_pin_read(PIN_KEY2) == PIN_LOW) )       )
        {
            rt_thread_mdelay(50);   /* 延时消抖*/
            key_up = 0;
            if (rt_pin_read(PIN_WK_UP) == PIN_HIGH)
            {
                /* 按键WK_UP按下,按键按下处理*/
                rt_kprintf("WK_UP pressed!\n");
            }
            else if (rt_pin_read(PIN_KEY0) == PIN_LOW)
            {
                /* 按键KEY0按下,按键按下处理*/
                rt_kprintf("KEY0 pressed!\n");
            }
            else if (rt_pin_read(PIN_KEY1) == PIN_LOW)
            {
                /* 按键KEY0按下,按键按下处理*/
                rt_kprintf("KEY1 pressed!\n");
            }
            else if (rt_pin_read(PIN_KEY2) == PIN_LOW)
            {
                /* 按键KEY0按下,按键按下处理*/
                rt_kprintf("KEY2 pressed!\n");
            }
        }
        else if((rt_pin_read(PIN_WK_UP) == PIN_LOW) &&
                (rt_pin_read(PIN_KEY0) == PIN_HIGH) &&
                (rt_pin_read(PIN_KEY1) == PIN_HIGH) &&
                (rt_pin_read(PIN_KEY2) == PIN_HIGH)     )
        {
            key_up = 1;     /* 按键已松开 */
        }
        rt_thread_mdelay(100);
    }

}


void app_key_init(void)
{
    rt_err_t rt_err;
#ifndef STATIC_METHON
    /* 创建按键检测线程*/
    key_thread = rt_thread_create(  "key thread",       /* 线程的名称 */
                                    key_thread_entry,   /* 线程入口函数 */
                                    RT_NULL,            /* 线程入口函数的参数   */
                                    256,                /* 线程栈大小,单位是字节  */
                                    5,                  /* 线程的优先级,数值越小优先级越高*/
                                    10);                /* 线程的时间片大小 */
    /* 如果获得线程控制块,启动这个线程 */
    if (key_thread != RT_NULL)
        rt_err = rt_thread_startup(key_thread);
    else
        rt_kprintf("key thread create failure !!! \n");

    /* 判断线程是否创建成功 */
    if( rt_err == RT_EOK)
        rt_kprintf("key thread startup ok. \n");
    else
        rt_kprintf("key thread startup err. \n");
#else
    /* 初始化按键检测线程,名称是thread2,入口是thread2_entry */
    rt_err = rt_thread_init(&key_thread,                /* 线程句柄 */
                           "key thread",                /* 线程的名称 */
                           key_thread_entry,            /* 线程入口函数 */
                           RT_NULL,                     /* 线程入口函数的参数   */
                           &key_thread_stack[0],        /* 线程栈起始地址*/
                           sizeof(key_thread_stack),    /* 线程栈大小,单位是字节*/
                           5,                           /* 线程的优先级,数值越小优先级越高*/
                           10);                         /* 线程的时间片大小 */
    /* 如果线程创建成功,启动这个线程 */
    if (rt_err == RT_EOK)
        rt_err = rt_thread_startup(&key_thread);
    else
        rt_kprintf("key thread init failure !!! \n");

    /* 判断线程是否启动成功 */
    if( rt_err == RT_EOK)
        rt_kprintf("key thread startup ok. \n");
    else
        rt_kprintf("key thread startup err. \n");
#endif
}

在mian()函数中调用app_key_init()
在这里插入图片描述
实现效果一样:
在这里插入图片描述

发布了62 篇原创文章 · 获赞 13 · 访问量 5572

猜你喜欢

转载自blog.csdn.net/qq_38113006/article/details/105336007