学习RT-thread(项目一:基于RT-thread的multi_button控制灯闪烁)

1. 项目说明:

  1. 板子包含三个按键,两个LED灯。按键1控制LED1,按键2控制LED2

  2. 按键1单击->LED1闪烁,按键1双击->LED1常亮,按键1长按->LED1常灭。

  3. 按键2单击->LED2闪烁,按键2双击->LED2常亮,按键2长按->LED2常灭。

  4. 按键的状态通过事件集方式通知LED状态。 5. 按键的控制采用multi_button组件,监测按键状态

2. 硬件说明:

开发板中,按键1接在PB5,按键2接在PA11,按键3接在PB3,LED1接在PA12,LED2接在PB4。如 下图:

3. multi_button组件

multi_button是利用线程的方式来检测按键输入的状态,它支持检测按键的单击,双击,长按三种状 态。

3.1 初始化按键:

cpp 复制代码
void button_init(button_t handle, uint8_t pin_index, uint8_t(*pin_level)(button_t 
handle), uint8_t active_level);

3.2 按键绑定事件回调:

cpp 复制代码
 void button_attach(button_t handle, uint8_t event, BtnCallback cb);

3.3 启动按键事件监控:

cpp 复制代码
启动按键事件监控: 
int  button_start(button_t handle);

3.4 暂停按键事件监控:

cpp 复制代码
void button_stop(button_t handle);

3.5 按键生命周期检测函数(注意:需要放在线程中调用)

cpp 复制代码
void button_ticks(void);

4.代码编写

CubeMX配置

代码编写

cpp 复制代码
#include "multi_button.h"
#include "stm32f1xx_hal.h"
#include <rtthread.h>

#define BTN_THREAD_STACK        1024
#define LED_THREAD_STACK        1024

#define BTN1_SIGLE_EVENT    (0X01 << 0)
#define BTN1_DOUBLE_EVENT   (0X01 << 1)
#define BTN1_LONG_EVENT     (0x01 << 2)

#define BTN2_SIGLE_EVENT    (0X01 << 3)
#define BTN2_DOUBLE_EVENT   (0X01 << 4)
#define BTN2_LONG_EVENT     (0x01 << 5)

#define BTN3_SIGLE_EVENT    (0X01 << 6)
#define BTN3_DOUBLE_EVENT   (0X01 << 7)
#define BTN3_LONG_EVENT     (0x01 << 8)

typedef enum{
    KEY1_INDEX=1,
    KEY2_INDEX,
    KEY3_INDEX,
    KEY_END
}bnt_key;

struct rt_event btn_event;

struct rt_thread btn_thread_handle;
static uint8_t btn_stack[BTN_THREAD_STACK];

struct rt_thread led_thread_handle;
static uint8_t led_stack[LED_THREAD_STACK];
 
static struct button key1_btn;
static struct button key2_btn;
static struct button key3_btn; 

void led_flash(rt_uint16_t index,rt_uint16_t event)
{
    if(index==KEY1_INDEX)
    {
        if(event==BTN1_SIGLE_EVENT)             
        {
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_RESET);
            rt_thread_delay(200);
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_SET);
            rt_thread_delay(200);
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_RESET);
            rt_thread_delay(200);
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_SET);
            rt_thread_delay(200);
        }
        else if(event==BTN1_DOUBLE_EVENT)
        {
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_RESET);
        }
        else
        {
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_SET);
        }
    }
    else if(index==KEY2_INDEX)
    {
         if(event==BTN2_SIGLE_EVENT)             
        {
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
            rt_thread_delay(200);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
            rt_thread_delay(200);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
            rt_thread_delay(200);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
            rt_thread_delay(200);
        }
        else if(event==BTN2_DOUBLE_EVENT)
        {
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
        }
        else
        {
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
        }
    }
    
}

void bnt_thread(void* parameter)      //线程里调用button的生命周期
{
    while(1)
    {
        /*     按键生命周期检测     */
        rt_thread_delay(5);
        button_ticks();
    }
}

void led_thread(void* parameter)      //led线程
{
    rt_uint32_t rev;
    while(1)
    {
        rt_event_recv(&btn_event,0xFFFFFFFF,RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR,RT_WAITING_FOREVER,&rev);
        switch(rev)
        {
            case BTN1_SIGLE_EVENT:
                led_flash(KEY1_INDEX,BTN1_SIGLE_EVENT);
                break;
            case BTN1_DOUBLE_EVENT:
                led_flash(KEY1_INDEX,BTN1_DOUBLE_EVENT);
                break;
            case BTN1_LONG_EVENT:
                led_flash(KEY1_INDEX,BTN1_LONG_EVENT);
                break;
            case BTN2_SIGLE_EVENT:
                led_flash(KEY2_INDEX,BTN2_SIGLE_EVENT);
                break;
            case BTN2_DOUBLE_EVENT:
                led_flash(KEY2_INDEX,BTN2_DOUBLE_EVENT);
                break;
            case BTN2_LONG_EVENT:
                led_flash(KEY2_INDEX,BTN2_LONG_EVENT);
                break;
            case BTN3_SIGLE_EVENT:
                break;
            case BTN3_DOUBLE_EVENT:
                break;
            case BTN3_LONG_EVENT:
                break;
            default:
                break;
        }
    }
}

uint8_t read_pin_level(button_t handle) //读电平的函数
{
    int index=handle->pin_index;
    if(index==KEY1_INDEX)
        return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5);
    else if(index==KEY2_INDEX)
        return HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11);
    else if(index==KEY3_INDEX)
        return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
    
}


void bnt_callback(button_t btn, PressEvent event) //当有事件产生的时候调用这个回调函数
{
    int index=btn->pin_index;
    
    if(index==KEY1_INDEX)
    {
        if(event==SINGLE_CLICK_EVENT)
        {
            rt_event_send(&btn_event,BTN1_SIGLE_EVENT);
            rt_kprintf("single,index:%d\n",index);
        }
            
        if(event==DOUBLE_CLICK_EVENT)
        {
            rt_event_send(&btn_event,BTN1_DOUBLE_EVENT);
            rt_kprintf("double,index:%d\n",index);
        }
            
        if(event==LONG_PRESS_HOLD_EVENT)
        {
            rt_event_send(&btn_event,BTN1_LONG_EVENT);
            rt_kprintf("long,index:%d\n",index);
        } 
    }
    else if(index==KEY2_INDEX)
    {
        if(event==SINGLE_CLICK_EVENT)
        {
            rt_event_send(&btn_event,BTN2_SIGLE_EVENT);
            rt_kprintf("single,index:%d\n",index);
        }
            
        if(event==DOUBLE_CLICK_EVENT)
        {
            rt_event_send(&btn_event,BTN2_DOUBLE_EVENT);
            rt_kprintf("double,index:%d\n",index);
        }
            
        if(event==LONG_PRESS_HOLD_EVENT)
        {
            rt_event_send(&btn_event,BTN2_LONG_EVENT);
            rt_kprintf("long,index:%d\n",index);
        } 
    }
    else if(index==KEY3_INDEX)
    {
        if(event==SINGLE_CLICK_EVENT)
        {
            rt_event_send(&btn_event,BTN3_SIGLE_EVENT);
            rt_kprintf("single,index:%d\n",index);
        }
            
        if(event==DOUBLE_CLICK_EVENT)
        {
            rt_event_send(&btn_event,BTN3_DOUBLE_EVENT);
            rt_kprintf("double,index:%d\n",index);
        }
            
        if(event==LONG_PRESS_HOLD_EVENT)
        {
            rt_event_send(&btn_event,BTN3_LONG_EVENT);
            rt_kprintf("long,index:%d\n",index);
        } 
    }
}


int riceboard_init()
{
    /*                  创建事件集                      */
    rt_event_init(&btn_event, "btn_event", RT_IPC_FLAG_PRIO);
    
     /*                 创建线程                        */
    rt_thread_init(&btn_thread_handle,"thread1",bnt_thread,NULL,btn_stack, 256,10,10);
    rt_thread_init(&led_thread_handle,"thread2",led_thread,NULL,led_stack, 256,10,10);
    
    rt_thread_startup(&btn_thread_handle);
    rt_thread_startup(&led_thread_handle);
    
    
    /*                 按键初始化                       */
    button_init(&key1_btn, KEY1_INDEX,read_pin_level, 0);
    button_init(&key2_btn, KEY2_INDEX,read_pin_level, 0);
    button_init(&key3_btn, KEY3_INDEX,read_pin_level, 0);
                                                          
    /*                  绑定按键                         */
    button_attach(&key1_btn,SINGLE_CLICK_EVENT|DOUBLE_CLICK_EVENT|LONG_PRESS_HOLD_EVENT, bnt_callback);
    button_attach(&key2_btn,SINGLE_CLICK_EVENT|DOUBLE_CLICK_EVENT|LONG_PRESS_HOLD_EVENT, bnt_callback);
    button_attach(&key3_btn,SINGLE_CLICK_EVENT|DOUBLE_CLICK_EVENT|LONG_PRESS_HOLD_EVENT, bnt_callback);
    
    /*               启动按键事件监控                    */
    button_start(&key1_btn);
    button_start(&key2_btn);
    button_start(&key3_btn);

}
INIT_APP_EXPORT(riceboard_init); //自动初始化函数

实验现象:

1.打开串口终端观察现象(灯光按预期效果闪烁、长亮、停止)

相关推荐
Jerry丶Li2 小时前
二十五、STM32的DMA(数据转运)
stm32·单片机·嵌入式硬件
Wu Liuqi3 小时前
【大模型学习4】大语言模型(LLM)详解
人工智能·学习·语言模型·大模型
CarmenHu3 小时前
RAFT微调学习笔记
笔记·学习
QiZhang | UESTC3 小时前
JAVA算法练习题day67
java·python·学习·算法·leetcode
李boyang3 小时前
I2C通信
单片机·嵌入式硬件·i2c
d111111111d4 小时前
STM32外设学习--ADC模数转换器--笔记
笔记·stm32·单片机·嵌入式硬件·学习
AC是你的谎言4 小时前
网络层和数据链路层
linux·网络·学习·智能路由器
Miki Makimura4 小时前
KVStore 多行文章型键值扩展解析:切片存储与客户端多行交互
运维·服务器·网络·学习
笨鸟笃行6 小时前
英语学习——单词篇(第十七天)
学习