原文作者: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
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!\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论坛
你点的每个“在看”,我都认真当成了喜欢