如何在之前创建的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 !!!  "); 6 7/* 判断线程是否启动成功 */ 8if( rt_err == RT_EOK) 9    rt_kprintf("key thread startup ok.  "); 10else 11    rt_kprintf("key thread startup err.  ");

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 !!!  "); 6 7    /* 判断线程是否启动成功 */ 8    if( rt_err == RT_EOK) 9        rt_kprintf("key thread startup ok.  "); 10    else 11        rt_kprintf("key thread startup err.  "); 

二、编写线程入口函数

首先,我们需要获取按键对应的引脚编号,使用 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! "); 25            } 26            else if (rt_pin_read(PIN_KEY0) == PIN_LOW) 27            { 28                /* 按键KEY0按下,按键按下处理*/ 29                rt_kprintf("KEY0 pressed! "); 30            } 31            else if (rt_pin_read(PIN_KEY1) == PIN_LOW) 32            { 33                /* 按键KEY0按下,按键按下处理*/ 34                rt_kprintf("KEY1 pressed! "); 35            } 36            else if (rt_pin_read(PIN_KEY2) == PIN_LOW) 37            { 38                /* 按键KEY0按下,按键按下处理*/ 39                rt_kprintf("KEY2 pressed! "); 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  2#include  3#include  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! "); 48            } 49            else if (rt_pin_read(PIN_KEY0) == PIN_LOW) 50            { 51                /* 按键KEY0按下,按键按下处理*/ 52                rt_kprintf("KEY0 pressed! "); 53            } 54            else if (rt_pin_read(PIN_KEY1) == PIN_LOW) 55            { 56                /* 按键KEY0按下,按键按下处理*/ 57                rt_kprintf("KEY1 pressed! "); 58            } 59            else if (rt_pin_read(PIN_KEY2) == PIN_LOW) 60            { 61                /* 按键KEY0按下,按键按下处理*/ 62                rt_kprintf("KEY2 pressed! "); 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 !!!  "); 94 95    /* 判断线程是否创建成功 */ 96    if( rt_err == RT_EOK) 97        rt_kprintf("key thread startup ok.  "); 98    else 99        rt_kprintf("key thread startup err.  "); 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 !!!  "); 115 116    /* 判断线程是否启动成功 */ 117    if( rt_err == RT_EOK) 118        rt_kprintf("key thread startup ok.  "); 119    else 120        rt_kprintf("key thread startup err.  "); 121#endif 122}

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

线程

实现效果一样:

线程

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分