RT-Thread 入门系列2—按键控制RGB
本节的主要内容有以下部分:
1、使用button软件包
2、按键控制创建线程
3、按键控制删除线程
1、使用button软件包
软件包在很大程度上大幅提升了开发效率,这也是RTOS的优势,所以我在第二篇就开始使用软件包,后需每个示例几乎都会用到软件包。实际项目中也可以直接应用。
1) 软件包的配置和选择
这个非常简单,只需点击添加,然后搜素button,然后保存就可以。
2)软件包的使用
软件包的使用也非常简单,但是对于初学者可能会遇到一些问题,一般的文件结构如下:
inc文件夹是包含的头文件,src是button功能的具体实现,使用简单的说明可以查看README.MD文件,或者直接点击package文件夹的根目录有操作实例,我们可以直接复制实例到main函数体验按键操作。
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-12 RT-Thread first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "ulog.h"
#include "agile_button.h"
#define LED_PIN GET_PIN(E,7)
#define PIN_LED_R GET_PIN(E, 7)
#define PIN_LED_B GET_PIN(E, 9)
#define PIN_LED_G GET_PIN(E, 8)
#define KEY0_PIN GET_PIN(D, 10)
static agile_btn_t *key0 = RT_NULL;
static void key_create(void);
int sys_clock_information(void)
{
LOG_D("System Clock information");
LOG_D("SYSCLK_Frequency = %d", HAL_RCC_GetSysClockFreq());
LOG_D("HCLK_Frequency = %d", HAL_RCC_GetHCLKFreq());
LOG_D("PCLK1_Frequency = %d", HAL_RCC_GetPCLK1Freq());
LOG_D("PCLK2_Frequency = %d", HAL_RCC_GetPCLK2Freq());
return RT_EOK;
}
int main(void)
{
int count = 1;
rt_pin_mode(LED_PIN,PIN_MODE_OUTPUT);
rt_pin_mode(PIN_LED_R,PIN_MODE_OUTPUT);
rt_pin_mode(PIN_LED_B,PIN_MODE_OUTPUT);
rt_pin_mode(PIN_LED_G,PIN_MODE_OUTPUT);
rt_pin_write(PIN_LED_R, PIN_HIGH);
rt_pin_write(PIN_LED_B, PIN_HIGH);
rt_pin_write(PIN_LED_G, PIN_HIGH);
key_create();
sys_clock_information();
while (count++)
{
// LOG_D("LED run times is %d.",count);
rt_pin_write(LED_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
return RT_EOK;
}
static void btn_click_event_cb(agile_btn_t *btn)
{
//rt_kprintf("light LED-BLUE !");
rt_pin_write(PIN_LED_B, PIN_LOW);
rt_thread_mdelay(100);
rt_pin_write(PIN_LED_B, PIN_HIGH);
rt_kprintf("[button click event] pin:%d repeat:%d, hold_time:%d\r\n", btn->pin, btn->repeat_cnt, btn->hold_time);
}
static void btn_hold_event_cb(agile_btn_t *btn)
{
//rt_pin_write(PIN_LED_B, PIN_HIGH);
rt_kprintf("[button hold event] pin:%d hold_time:%d\r\n", btn->pin, btn->hold_time);
}
static void key_create(void)
{
if(key0 == RT_NULL)
{
key0 = agile_btn_create(KEY0_PIN, PIN_LOW, PIN_MODE_INPUT_PULLUP);
agile_btn_set_event_cb(key0, BTN_CLICK_EVENT, btn_click_event_cb);
agile_btn_set_event_cb(key0, BTN_HOLD_EVENT, btn_hold_event_cb);
agile_btn_start(key0);
}
}
初始化了RGB灯的管脚和按键0,按下按键会有蓝灯亮一下。软件包的使用则是直接复制例程上的操作。十分方便。如果要自己写按键的驱动还是需要一些时间的。使用软件包还是比较高效的。
2、按键控制创建线程
按键控制其实比较复杂的,按键本身有多种信号,比如下降沿,上升沿,长按,短按。至少这4种状态。另外还有在按键的回调函数中的操作,一般是释放信号量来传递按键信息。
尝试在一个线程创建另一个线程,测试后发现硬件错误,无法实现。具体原因也不清楚,没有找到,后续对系统有更升入的了解的时候再来回答,还是采用一些通用的方法,释放信号量来实现另一个线程的创建。
enum agile_btn_state
{
BTN_STATE_NONE_PRESS = 0,
BTN_STATE_CHECK_PRESS,
BTN_STATE_PRESS_DOWN, //按下
BTN_STATE_PRESS_HOLD, //长按
BTN_STATE_PRESS_UP, // 弹起
};
从上面可以看到软件包总的按键状态,分为按下,弹起,长按,没哟按下。
关于按键的操作都在.h文件中,可以根据如下函数进行操作。
agile_btn_t *agile_btn_create(rt_base_t pin, rt_base_t active_logic, rt_base_t pin_mode);
// 删除按键对象
int agile_btn_delete(agile_btn_t *btn);
// 启动按键
int agile_btn_start(agile_btn_t *btn);
// 停止按键
int agile_btn_stop(agile_btn_t *btn);
// 设置按键消抖时间
int agile_btn_set_elimination_time(agile_btn_t *btn, uint8_t elimination_time);
// 设置按键按下后BTN_HOLD_EVENT事件回调函数的周期
int agile_btn_set_hold_cycle_time(agile_btn_t *btn, uint32_t hold_cycle_time);
// 设置按键事件回调函数
int agile_btn_set_event_cb(agile_btn_t *btn, enum agile_btn_event event, void (*event_cb)(agile_btn_t *btn));
关于信号量的创建: