【RT-Thread Studio入门】使用轮询法检测按键

原文作者:Willliam_william

https://blog.csdn.net/qq_38113006?t=1

上期回顾:

【RT-Thread Studio入门】创建第一个Hello world项目

本期我们将讲解,如何在之前创建的Hello World项目中添加按键检测功能。

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

1、使用动态线程创建方法创建一个线程

首先,定义一个动态线程句柄结构体指针:

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

然后使用动态线程创建函数创建一个线程,其中线程优先级的范围根据系统配置情况不同,

可以在rtconfig.h中查看RT_THREAD_PRIORITY_MAX 宏定义

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

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

 1/* 如果获得线程控制块,启动这个线程 */
 2if (key_thread != RT_NULL)
 3    rt_err = rt_thread_startup(key_thread);
 4else
 5    rt_kprintf("key thread create failure !!! \n");
 6
 7/* 判断线程是否启动成功 */
 8if( rt_err == RT_EOK)
 9    rt_kprintf("key thread startup ok. \n");
10else
11    rt_kprintf("key thread startup err. \n");

2、使用静态线程创建方法创建一个线程

静态线程创建需要提供线程栈和句柄:

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

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

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

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

 1    /* 如果线程创建成功,启动这个线程 */
 2    if (rt_err == RT_EOK)
 3        rt_err = rt_thread_startup(&key_thread);
 4    else
 5        rt_kprintf("key thread init failure !!! \n");
 6
 7    /* 判断线程是否启动成功 */
 8    if( rt_err == RT_EOK)
 9        rt_kprintf("key thread startup ok. \n");
10    else
11        rt_kprintf("key thread startup err. \n");

二、编写线程入口函数

首先,我们需要获取按键对应的引脚编号,使用 GET_PIN 宏定义,查看原理图,获取按键对应的引脚

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

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

 1/* 按键检测线程入口函数*/
 2static void key_thread_entry(void *parameter)
 3{
 4    static rt_uint8_t key_up = 1;   /* 按键松开标志 */
 5    /* 初始化按键 */
 6    rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT);
 7    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);
 8    rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT);
 9    rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT);
10
11    while (1)
12    {
13        /* 检测按键是否按下 */
14        if (key_up && ((rt_pin_read(PIN_WK_UP) == PIN_HIGH) ||
15                      (rt_pin_read(PIN_KEY0) == PIN_LOW)    ||
16                      (rt_pin_read(PIN_KEY1) == PIN_LOW)    ||
17                      (rt_pin_read(PIN_KEY2) == PIN_LOW) )       )
18        {
19            rt_thread_mdelay(50);   /* 延时消抖*/
20            key_up = 0;
21            if (rt_pin_read(PIN_WK_UP) == PIN_HIGH)
22            {
23                /* 按键WK_UP按下,按键按下处理*/
24                rt_kprintf("WK_UP pressed!\n");
25            }
26            else if (rt_pin_read(PIN_KEY0) == PIN_LOW)
27            {
28                /* 按键KEY0按下,按键按下处理*/
29                rt_kprintf("KEY0 pressed!\n");
30            }
31            else if (rt_pin_read(PIN_KEY1) == PIN_LOW)
32            {
33                /* 按键KEY0按下,按键按下处理*/
34                rt_kprintf("KEY1 pressed!\n");
35            }
36            else if (rt_pin_read(PIN_KEY2) == PIN_LOW)
37            {
38                /* 按键KEY0按下,按键按下处理*/
39                rt_kprintf("KEY2 pressed!\n");
40            }
41        }
42        else if((rt_pin_read(PIN_WK_UP) == PIN_LOW) &&
43                (rt_pin_read(PIN_KEY0) == PIN_HIGH) &&
44                (rt_pin_read(PIN_KEY1) == PIN_HIGH) &&
45                (rt_pin_read(PIN_KEY2) == PIN_HIGH)     )
46        {
47            key_up = 1;     /* 按键已松开 */
48        }
49        rt_thread_mdelay(100);
50    }
51
52}

三、实现效果

构建并下载程序,查看串口终端输出:

可以看到,按键检测线程启动成功,按键功能也实现了

四、代码优化

上面我们的代码都写在了mian.c里,我们可以将其放在一个单独的app_key.c文件中右键选中【applications】,选择新建源文件

输入 app_key.c文件名,点击确定:

将之前编写的代码都迁移到该文件中来,并提供一个app_key_init()函数供main()函数调用

  1#include <rtthread.h>
  2#include <rtdevice.h>
  3#include <board.h>
  4
  5/* 使用静态方法线程创建*/
  6#define STATIC_METHON
  7
  8#ifndef STATIC_METHON
  9/* 定义一个按键检测线程句柄结构体指针 */
 10static rt_thread_t key_thread = RT_NULL;
 11#else
 12/*定义一个按键检测静态线程栈*/
 13static char key_thread_stack[256];
 14/*定义一个按键检测静态线程句柄*/
 15static struct rt_thread key_thread;
 16#endif
 17
 18/* 获取相应的引脚编号 */
 19#define PIN_WK_UP   GET_PIN(C, 13)
 20#define PIN_KEY0    GET_PIN(D, 10)
 21#define PIN_KEY1    GET_PIN(D, 9)
 22#define PIN_KEY2    GET_PIN(D, 8)
 23
 24/* 按键检测线程入口函数*/
 25static void key_thread_entry(void *parameter)
 26{
 27    static rt_uint8_t key_up = 1;   /* 按键松开标志 */
 28    /* 初始化按键 */
 29    rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT);
 30    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);
 31    rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT);
 32    rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT);
 33
 34    while (1)
 35    {
 36        /* 检测按键是否按下 */
 37        if (key_up && ((rt_pin_read(PIN_WK_UP) == PIN_HIGH) ||
 38                      (rt_pin_read(PIN_KEY0) == PIN_LOW)    ||
 39                      (rt_pin_read(PIN_KEY1) == PIN_LOW)    ||
 40                      (rt_pin_read(PIN_KEY2) == PIN_LOW) )       )
 41        {
 42            rt_thread_mdelay(50);   /* 延时消抖*/
 43            key_up = 0;
 44            if (rt_pin_read(PIN_WK_UP) == PIN_HIGH)
 45            {
 46                /* 按键WK_UP按下,按键按下处理*/
 47                rt_kprintf("WK_UP pressed!\n");
 48            }
 49            else if (rt_pin_read(PIN_KEY0) == PIN_LOW)
 50            {
 51                /* 按键KEY0按下,按键按下处理*/
 52                rt_kprintf("KEY0 pressed!\n");
 53            }
 54            else if (rt_pin_read(PIN_KEY1) == PIN_LOW)
 55            {
 56                /* 按键KEY0按下,按键按下处理*/
 57                rt_kprintf("KEY1 pressed!\n");
 58            }
 59            else if (rt_pin_read(PIN_KEY2) == PIN_LOW)
 60            {
 61                /* 按键KEY0按下,按键按下处理*/
 62                rt_kprintf("KEY2 pressed!\n");
 63            }
 64        }
 65        else if((rt_pin_read(PIN_WK_UP) == PIN_LOW) &&
 66                (rt_pin_read(PIN_KEY0) == PIN_HIGH) &&
 67                (rt_pin_read(PIN_KEY1) == PIN_HIGH) &&
 68                (rt_pin_read(PIN_KEY2) == PIN_HIGH)     )
 69        {
 70            key_up = 1;     /* 按键已松开 */
 71        }
 72        rt_thread_mdelay(100);
 73    }
 74
 75}
 76
 77
 78void app_key_init(void)
 79{
 80    rt_err_t rt_err;
 81#ifndef STATIC_METHON
 82    /* 创建按键检测线程*/
 83    key_thread = rt_thread_create(  "key thread",       /* 线程的名称 */
 84                                    key_thread_entry,   /* 线程入口函数 */
 85                                    RT_NULL,            /* 线程入口函数的参数   */
 86                                    256,                /* 线程栈大小,单位是字节  */
 87                                    5,                  /* 线程的优先级,数值越小优先级越高*/
 88                                    10);                /* 线程的时间片大小 */
 89    /* 如果获得线程控制块,启动这个线程 */
 90    if (key_thread != RT_NULL)
 91        rt_err = rt_thread_startup(key_thread);
 92    else
 93        rt_kprintf("key thread create failure !!! \n");
 94
 95    /* 判断线程是否创建成功 */
 96    if( rt_err == RT_EOK)
 97        rt_kprintf("key thread startup ok. \n");
 98    else
 99        rt_kprintf("key thread startup err. \n");
100#else
101    /* 初始化按键检测线程,名称是thread2,入口是thread2_entry */
102    rt_err = rt_thread_init(&key_thread,                /* 线程句柄 */
103                           "key thread",                /* 线程的名称 */
104                           key_thread_entry,            /* 线程入口函数 */
105                           RT_NULL,                     /* 线程入口函数的参数   */
106                           &key_thread_stack[0],        /* 线程栈起始地址*/
107                           sizeof(key_thread_stack),    /* 线程栈大小,单位是字节*/
108                           5,                           /* 线程的优先级,数值越小优先级越高*/
109                           10);                         /* 线程的时间片大小 */
110    /* 如果线程创建成功,启动这个线程 */
111    if (rt_err == RT_EOK)
112        rt_err = rt_thread_startup(&key_thread);
113    else
114        rt_kprintf("key thread init failure !!! \n");
115
116    /* 判断线程是否启动成功 */
117    if( rt_err == RT_EOK)
118        rt_kprintf("key thread startup ok. \n");
119    else
120        rt_kprintf("key thread startup err. \n");
121#endif
122}

在mian()函数中调用app_key_init()

实现效果一样:

RT-Thread论坛原创征稿活动:与RT-Thread相关即可,内容题材不限。参与即有机会赢得,RT-Thread T恤、笔记本、技术书籍、京东卡、RT-Thread能力认证优惠券等  

马上参与

参与入口:https://www.rt-thread.org/qa/thread-424281-1-1.html


你可以添加微信17775982065为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群!

RT-Thread


让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。Apache2.0协议,可免费在商业产品中使用,不需要公布源码,无潜在商业风险。

长按二维码,关注我们

点击阅读原文,进入RT-Thread论坛

你点的每个“在看”,我都认真当成了喜欢

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值