按键在嵌入式系统中起着举足轻重的意义!!你们平时使用的苹果手表,手机,遥控器,空调开关,电视机,各种家用电器都有按键,这些按键都是通过嵌入式的实体按键来实现功能的。

RA4L1_SENSOR-V1原理图上总共有两个按键,分别是P000和P001,内部上拉输入。低电平有效,代表按下。
好了,直接上干货,一顿操作猛如虎!!!!!!
1。打开瑞萨的RA smart配置软件
先配置P000

然后配置P001

2。点击生成代码。

关闭smart软件,打开KEIL工程

看到新的配置已经生效
在工程中加入按键库


#include "ebtn_custom_callback.h"
#include "usart9.h"
/* ---------------------------- 此函数中可自定义按键状态检测方�?---------------------------- */
/** ***************************************************************************
-
@brief 获取按键状态回调函�?
-
此函数默认采用了查表检测,免去需要手动为每个按键添加检测方�?
-
也可为特殊按键自定义检测方�?
-
@note 查表检测需要配合ebtn_custom_config.c中的按键配置结构体数组使�?
-
@param btn: easy_button按键结构体指�?
-
@return 按键状态,0表示未按下,1表示按下
*/
uint8_t ebtn_Get_State(struct ebtn_btn *btn)
{
// 查表法检�?
for (int i = 0; i < key_list_size; i++)
{
if (key_list[i].key_id == btn->key_id)
{
uint8_t pin_state = ebtn_custom_hal.Read_Pin(key_list[i].p_ctrl, key_list[i].gpio_pin);
// 根据有效电平转换
if (key_list[i].active_level == pin_state)
{
pin_state = 1;
}
else
{
pin_state = 0;
}
return pin_state;
}
}
/* ----------------------------- 此处可自定义按键状态获取方�?----------------------------- */
// 可自定义特殊按键的检测方式,如矩阵按键的检�?
return 0; // 未找到按键ID,返�?
}
/* ------------------------------- 此函数可修改按键触发事件 ------------------------------- */
/** ***************************************************************************
-
@brief 按键事件处理回调函数,在此定义按键触发事�?
-
推荐将不同按键或事件的处理逻辑拆分为独立的函数,并参考原有的 switch(ebtn->key) 结构�?
-
在对应按键编号的 case 分支中调用相应的处理函数,以提升代码的可读性和可维护�?
-
@param btn: easy_button按键结构体指�?
-
@param evt: 事件类型
*/
void ebtn_Event_Handler(struct ebtn_btn btn, ebtn_evt_t evt)
{
switch (btn->key_id) // 按键ID
{
/ ---------------------------------- KEY1 ---------------------------------- /
case KEY_1:
/ ---------------------------------- 按下按键�?--------------------------------- /
if (evt == EBTN_EVT_ONPRESS)
{
}
/ ---------------------------------- 松开按键�?--------------------------------- /
else if (evt == EBTN_EVT_ONRELEASE)
{
//button_count = 1;
}
/ ----------------------------- 短按按键时(可获取连击次数) ----------------------------- /
else if (evt == EBTN_EVT_ONCLICK)
{
/ ----------------------------------- 单击�?---------------------------------- /
if (btn->click_cnt == 1)
{
button_count = 1;
}
/ ----------------------------------- 双击�?---------------------------------- /
else if (btn->click_cnt == 2)
{
button_count = 2;
}
/ ----------------------------------- 三击�?---------------------------------- /
else if (btn->click_cnt == 3)
{
button_count = 3;
}
}
/ ------------------------- 长按达到最短时间(配置默认600ms),触发长按计数�?------------------------ /
else if (evt == EBTN_EVT_KEEPALIVE)
{
/ ------------------------------- 长按计数到达指定值时 ------------------------------- /
if (btn->keepalive_cnt == 1)
{
button_count = 4;
}
else if (btn->keepalive_cnt == 2)
{
button_count = 5;
}
else if (btn->keepalive_cnt == 3)
{
button_count = 6;
}
}
break;
/ ----------------------------------- KEY2 ---------------------------------- /
case KEY_2:
/ ---------------------------------- 按下按键�?--------------------------------- /
if (evt == EBTN_EVT_ONPRESS)
{
}
/ ---------------------------------- 松开按键�?--------------------------------- /
else if (evt == EBTN_EVT_ONRELEASE)
{
}
/ ----------------------------- 短按按键时(可获取连击次数) ----------------------------- /
else if (evt == EBTN_EVT_ONCLICK)
{
/ ----------------------------------- 单击�?---------------------------------- /
if (btn->click_cnt == 1)
{
button_count = 1;
}
/ ----------------------------------- 双击�?---------------------------------- /
else if (btn->click_cnt == 2)
{
button_count = 2;
}
/ ----------------------------------- 三击�?---------------------------------- */
else if (btn->click_cnt == 3)
{
button_count = 3;
}
}
else if (evt == EBTN_EVT_KEEPALIVE)
{
if (btn->keepalive_cnt == 1)
{
button_count = 4;
}
else if (btn->keepalive_cnt == 2)
{
button_count = 5;
}
else if (btn->keepalive_cnt == 3)
{
button_count = 6;
}
}
break;
case COMBO_KEY_1:
/* ---------------------------------- 按下按键�?--------------------------------- /
if (evt == EBTN_EVT_ONPRESS)
{
button_count = 7;
}
/ ---------------------------------- 松开按键�?--------------------------------- */
else if (evt == EBTN_EVT_ONRELEASE)
{
button_count = 8;
}
break;
case COMBO_KEY_2:
/* ---------------------------------- 按下按键�?--------------------------------- /
if (evt == EBTN_EVT_ONPRESS)
{
}
/ ---------------------------------- 松开按键�?--------------------------------- */
else if (evt == EBTN_EVT_ONRELEASE)
{
}
break;
case COMBO_KEY_3:
/* ---------------------------------- 按下按键�?--------------------------------- /
if (evt == EBTN_EVT_ONPRESS)
{
}
/ ---------------------------------- 松开按键�?--------------------------------- */
else if (evt == EBTN_EVT_ONRELEASE)
{
}
break;
case COMBO_KEY_4:
/* ---------------------------------- 按下按键�?--------------------------------- /
if (evt == EBTN_EVT_ONPRESS)
{
}
/ ---------------------------------- 松开按键�?--------------------------------- */
else if (evt == EBTN_EVT_ONRELEASE)
{
}
break;
}
}

按键核心处理函数




上面是按键的处理函数,包括KE1的单击,双击,三击,连击,
KE2的单击,双击,三击,连击。非常丰富
按键的注册函数
#include "ebtn_custom_config.h"
/** ***************************************************************************
- @brief 定义按键参数结构体
- @ref ebtn_Custom_x.h
*/
ebtn_btn_param_t buttons_parameters = EBTN_PARAMS_INIT(
DEBOUNCE_TIME, // 按下防抖超时
RELEASE_DEBOUNCE_TIME, // 松开防抖超时
CLICK_AND_PRESS_MIN_TIME, // 按键最短时间
CLICK_AND_PRESS_MAX_TIME, // 按键最长时间
MULTI_CLICK_MAX_TIME, // 连续点击最大间隔(ms)
KEEPALIVE_TIME_PERIOD, // 长按报告事件间隔(ms)
MAX_CLICK_COUNT // 最大连续点击次数
);
/* --------------------------------- 此处修改按键 --------------------------------- */
// 所需的按键ID定义在ebtn_custom_config.h中增添
/** ***************************************************************************
- @brief 按键列表结构体数组,用于将按键ID与GPIO引脚以及触发电平进行绑定,
- 同时使用查表检测,免去需要为每个按键手动添加检测方式
- @note 此处填入所需的按键ID及其GPIO信息和触发时电平
*/
ebtn_custom_config_key_list_t key_list[] = {
// 示例:4个按键
{KEY_1, GPIOX, BSP_IO_PORT_00_PIN_00, 0}, // KEY_1按键,P000,低电平有效
{KEY_2, GPIOX, BSP_IO_PORT_00_PIN_01, 0}, // KEY_2按键,P001,低电平有效
// {KEY_3, GPIOB, GPIO_Pin_1, 0}, // KEY_3按键,PB1,低电平有效
// {KEY_4, GPIOB, GPIO_Pin_12, 0}, // KEY_4按键,PB12,低电平有效
};
/** ***************************************************************************
- @brief 按键结构体数组,用于将按键ID与按键参数进行绑定
- @note 此为静态注册方法,动态注册详见easy_button库Github仓库
*/
ebtn_btn_t btn_array[] = {
EBTN_BUTTON_INIT(KEY_1, &buttons_parameters),
EBTN_BUTTON_INIT(KEY_2, &buttons_parameters),
//EBTN_BUTTON_INIT(KEY_3, &buttons_parameters),
//EBTN_BUTTON_INIT(KEY_4, &buttons_parameters),
};
/** ***************************************************************************
- @brief 组合键结构体数组,用于将多个按键组合成一个按键进行事件判断
- @note 此为静态注册方法,动态注册详见easy_button库Github仓库
- @note 需要在ebtn_app.c的ebtn_APP_Key_INIT函数中使用ebtn_Combo_btn_add_btn向组合键结构体数组添加对应按键
- 其中结构体数组索引与此处结构体数组的索引顺序一致,详见ebtn_app.c
*/
ebtn_btn_combo_t btn_combo_array[] = {
EBTN_BUTTON_COMBO_INIT(COMBO_KEY_1, &buttons_parameters),
//EBTN_BUTTON_COMBO_INIT(COMBO_KEY_2, &buttons_parameters),
//EBTN_BUTTON_COMBO_INIT(COMBO_KEY_3, &buttons_parameters),
//EBTN_BUTTON_COMBO_INIT(COMBO_KEY_4, &buttons_parameters),
};
/* -------------------------------- 自定义配置部分结束 ------------------------------- */
const uint8_t btn_array_size = EBTN_ARRAY_SIZE(btn_array);
const uint8_t btn_combo_array_size = EBTN_ARRAY_SIZE(btn_combo_array);
const uint8_t key_list_size = EBTN_ARRAY_SIZE(key_list);


#ifndef EBTN_CUSTOM_CONFIG_H
#define EBTN_CUSTOM_CONFIG_H
#include "ebtn.h"
#include "ebtn_custom_hal.h"
/* -------------------------------- 此处修改按键参数定义 -------------------------------- */
#define DEBOUNCE_TIME 20 // 防抖处理,按下防抖超时,配置为0,代表不启用
#define RELEASE_DEBOUNCE_TIME 20 // 防抖处理,松开防抖超时,配置为0,代表不启用
#define CLICK_AND_PRESS_MIN_TIME 20 // 按键超时处理,触发最短时间,小于该时间则不触发Click和Press,配置为0,代表不检查最小值。用于防误触
#define CLICK_AND_PRESS_MAX_TIME 200 // 按键超时处理,短按最长时间,配置为0xFFFF,代表不检查最大值。用于区分长按和短按事件,大于该时间则不触发Click而触发Press
#define MULTI_CLICK_MAX_TIME 200 // 多击处理超时结算,两个按键之间的时间是连击的超时时间(ms)
#define KEEPALIVE_TIME_PERIOD 600 // 长按处理,长按周期,每个周期增加keepalive_cnt计数(ms)
#define MAX_CLICK_COUNT 3 // 最大连续短击次数,配置为0,代表不进行连击检查
/* -------------------------------- 此处修改按键ID定义 -------------------------------- */
/** ***************************************************************************
- @brief 按键ID枚举
- @note 此处定义按键ID
*/
typedef enum
{
// 示例:4个按键和四个组合键,包含最大按键,用于提供按键数量
KEY_1,
KEY_2,
KEY_3,
KEY_4,
MAX_KEY, // 最大按键,用于提供按键数量
COMBO_KEY_1,
COMBO_KEY_2,
COMBO_KEY_3,
COMBO_KEY_4,
MAX_COMBO_KEY // 最大组合键,用于提供组合键数量
} ebtn_custom_config_key_enum_t;
/* ---------------------------------- 自定义配置部分结束 ---------------------------------- */
/** ***************************************************************************
- @brief 自定义按键配置结构体宏定义
*/
typedef struct
{
uint16_t key_id; // 按键按键ID
//GPIO_TypeDef *gpio_port; // GPIO端口
ioport_ctrl_t * const p_ctrl;// GPIO端口
uint16_t gpio_pin; // GPIO引脚
uint8_t active_level; // 有效电平(0=低电平有效,1=高电平有效)
} ebtn_custom_config_key_list_t;
extern ebtn_custom_config_key_list_t key_list[]; // 按键配置数组
extern ebtn_btn_t btn_array[]; // 按键结构体数组
extern ebtn_btn_combo_t btn_combo_array[]; // 组合键结构体数组
extern const uint8_t btn_array_size; // 按键结构体数组大小
extern const uint8_t btn_combo_array_size; // 组合键结构体数组大小
extern const uint8_t key_list_size; // 按键配置数组大小
#endif /* EBTN_CUSTOM_CONFIG_H */

#ifndef EBTN_CUSTOM_HAL_H
#define EBTN_CUSTOM_HAL_H
/* ------------------------------ 此处包含单片机平台的头文件 ----------------------------- */
// 包含单片机平台的声明了GPIO和SysTick相关的头文件
#include "hal_data.h"
#include "usart9.h"
#include <stdint.h>
#include "bsp_api.h"
#include "r_ioport.h"
#include "r_ioport_api.h"
#define GPIOX &g_ioport_ctrl
/* -------------------------- 此处修改硬件回调函数自定义声明(如有需求) ------------------------- */
/** ***************************************************************************
- @brief 自定义回调函数结构体声明
/
typedef struct
{
/* ***************************************************************************
- @brief 读取GPIO电平,在ebtn_app.c中被使用,用于读取按键引脚的电平
- @param p_ctrl 指向GPIO端口的指针
- @param pin GPIO引脚号
- @return GPIO引脚的电平状态(0/1)
/
uint8_t (Read_Pin)(ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin);
/ ***************************************************************************
- @brief 获取系统滴答计数器值,用于为ebtn_process()函数提供时间基准
- @note SysTick时基为1ms
- @return 系统滴答计数器ms时间值
*/
uint32_t (*Get_Tick)(void);
} ebtn_custom_hal_t;
/* -------------------------------- 自定义配置部分结束 ------------------------------- */
extern ebtn_custom_hal_t ebtn_custom_hal; // ebtn适配层回调函数结构声明
#endif /* EBTN_CUSTOM_HAL_H */
实现按键按下判断函数
#include "ebtn_custom_hal.h"
/* ------------------------------ 此处实现硬件抽象回调函数 ------------------------------ */
/** ***************************************************************************
- @brief 读取GPIO电平,在ebtn_app.c中被使用,用于读取按键引脚的电平
- @param GPIOx 指向GPIO端口的指针
- @param GPIO_Pin GPIO引脚号
- @return GPIO引脚的电平状态(0/1)
/
/
uint8_t ebtn_HAL_Read_Pin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
return (uint8_t)HAL_GPIO_ReadPin(GPIOx, GPIO_Pin); // 示例:STM32HAL库;强制转换uint8_t类型,确保通用性
}
*/
uint8_t ebtn_HAL_Read(ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin)
{
bsp_io_level_t S1;
R_IOPORT_PinRead(p_ctrl,pin,&S1);
return S1;
}
/** ***************************************************************************
- @brief 获取系统滴答计数器值,用于为ebtn_process()函数提供时间基准
- @note SysTick时基为1ms
- @return 系统滴答计数器ms时间值
*/
uint32_t ebtn_HAL_Get_Tick(void)
{
return hal_systick_get();
}
/* -------------------------------- 自定义配置部分结束 ------------------------------- */
/** ***************************************************************************
- @brief ebtn_Custom回调函数结构体实例化
*/
ebtn_custom_hal_t ebtn_custom_hal = {
//.Read_Pin = ebtn_HAL_Read_Pin,
.Read_Pin = ebtn_HAL_Read,
.Get_Tick = ebtn_HAL_Get_Tick,
};

#include "ebtn_app.h"
/* -------------------------------- 初始化和处理函数 -------------------------------- */
/** ***************************************************************************
-
@brief easy_button初始化,在主函数中调用
-
@note 如果使用组合键,则需要在ebtn_init之后调用ebtn_combo_btn_add_btn添加组合键
*/
void ebtn_APP_Key_INIT(void)
{
// 初始化easy_button库
ebtn_init(btn_array, btn_array_size,
btn_combo_array, btn_combo_array_size,
ebtn_Get_State, ebtn_Event_Handler);
/* ---------------------------- 此处向组合键结构体数组静态添加按键 --------------------------- */
// 结构体数组索引值与ebtn_custom_config.c中组合键结构体数组btn_combo_array中的索引值一致
// 示例:四个组合键
// 为组合键1添加按键KEY_1和KEY_2
// ebtn_combo_btn_add_btn(&btn_combo_array[0], KEY_1);
// ebtn_combo_btn_add_btn(&btn_combo_array[0], KEY_2);
// // 为组合键2添加按键KEY_3和KEY_4
// ebtn_combo_btn_add_btn(&btn_combo_array[1], KEY_3);
// ebtn_combo_btn_add_btn(&btn_combo_array[1], KEY_4);
// // 为组合键3添加按键KEY_1和KEY_3
// ebtn_combo_btn_add_btn(&btn_combo_array[2], KEY_1);
// ebtn_combo_btn_add_btn(&btn_combo_array[2], KEY_3);
// // 为组合键4添加按键KEY_2和KEY_4
// ebtn_combo_btn_add_btn(&btn_combo_array[3], KEY_2);
// ebtn_combo_btn_add_btn(&btn_combo_array[3], KEY_4);
}
/* --------------------------------- 自定义配置部分结束 -------------------------------- */
/** ***************************************************************************
- @brief 处理按键事件,需要定期调用,建议以20ms为周期执行一次
- @note Tick时基为1ms
*/
void ebtn_APP_Key_Process(void)
{
ebtn_process(ebtn_custom_hal.Get_Tick()); // 获取时间处理按键事件
}
/* -------------------------------- 辅助部分 ------------------------------- */
/** ***************************************************************************
- @brief 检查按键是否激活
- @param key_id: 按键ID
- @return uint8_t: 1-激活,0-未激活
*/
uint8_t ebtn_APP_Is_Key_Active(uint16_t key_id)
{
ebtn_btn_t *btn = ebtn_get_btn_by_key_id(key_id);
return ebtn_is_btn_active(btn);
}
/** ***************************************************************************
- @brief 检查是否有按键处于处理中
- @return uint8_t: 1-有按键处理中,0-无按键处理中
*/
uint8_t ebtn_APP_Is_Any_Key_In_Process(void)
{
return ebtn_is_in_process();
}
/** ***************************************************************************
-
@brief 获取指定按键的按键状态
-
@param key_id: 按键ID
-
@return uint8_t: 1-按下,0-松开
*/
uint8_t ebtn_APP_Get_Key_State(uint16_t key_id)
{
ebtn_btn_t *btn = ebtn_get_btn_by_key_id(key_id);
if (btn == NULL)
{
return 0;
}
return ebtn_Get_State(btn);
}



#ifndef _EBTN_H
#define _EBTN_H
#include <stdint.h>
#include <string.h>
#include "bit_array.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
// #define EBTN_CONFIG_TIMER_16
// here can change to uint16_t, if you want reduce RAM size.
#ifdef EBTN_CONFIG_TIMER_16
typedef uint16_t ebtn_time_t;
typedef int16_t ebtn_time_sign_t;
#else
typedef uint32_t ebtn_time_t;
typedef int32_t ebtn_time_sign_t;
#endif
/* Forward declarations */
struct ebtn_btn;
struct ebtn;
#define EBTN_MAX_KEYNUM (64)
/**
- \brief List of button events
/
typedef enum
{
EBTN_EVT_ONPRESS = 0x00, /!< On press event - sent when valid press is detected /
EBTN_EVT_ONRELEASE, /!< On release event - sent when valid release event is detected (from
active to inactive) /
EBTN_EVT_ONCLICK, /!< On Click event - sent when valid sequence of on-press and on-release
events occurs /
EBTN_EVT_KEEPALIVE, /!< Keep alive event - sent periodically when button is active */
} ebtn_evt_t;
#define EBTN_EVT_MASK_ONPRESS (1 << EBTN_EVT_ONPRESS)
#define EBTN_EVT_MASK_ONRELEASE (1 << EBTN_EVT_ONRELEASE)
#define EBTN_EVT_MASK_ONCLICK (1 << EBTN_EVT_ONCLICK)
#define EBTN_EVT_MASK_KEEPALIVE (1 << EBTN_EVT_KEEPALIVE)
#define EBTN_EVT_MASK_ALL (EBTN_EVT_MASK_ONPRESS | EBTN_EVT_MASK_ONRELEASE | EBTN_EVT_MASK_ONCLICK | EBTN_EVT_MASK_KEEPALIVE)
/**
- @brief Returns the difference between two absolute times: time1-time2.
- @param[in] time1: Absolute time expressed in internal time units.
- @param[in] time2: Absolute time expressed in internal time units.
- @return resulting signed relative time expressed in internal time units.
*/
static inline ebtn_time_sign_t ebtn_timer_sub(ebtn_time_t time1, ebtn_time_t time2)
{
return time1 - time2;
}
// test time overflow error
// #define ebtn_timer_sub(time1, time2) (time1 - time2)
/**
- \brief Button event function callback prototype
- \param[in] btn: Button instance from array for which event occured
- \param[in] evt: Event type
*/
typedef void (*ebtn_evt_fn)(struct ebtn_btn *btn, ebtn_evt_t evt);
/**
- \brief Get button/input state callback function
- \param[in] btn: Button instance from array to read state
- \return
1 when button is considered active, 0 otherwise
*/
typedef uint8_t (*ebtn_get_state_fn)(struct ebtn_btn *btn);
/**
-
\brief Button Params structure
/
typedef struct ebtn_btn_param
{
/*
/
uint16_t time_debounce; /!< Debounce time in milliseconds */
/**
- \brief Minimum debounce time for release event in units of milliseconds
- This is the time when the input shall have minimum stable released level to detect valid
- onrelease event.
- This setting can be useful if application wants to protect against
- unwanted glitches on the line when input is considered "active".
- When value is set to
> 0, input must be in inactive low for at least
- minimum milliseconds time, before valid onrelease event is detected
- \note If value is set to
0, debounce is not used and release event will be
- triggered immediately when input states goes to inactive state
/
uint16_t time_debounce_release; /!< Debounce time in milliseconds for release event */
/**
- \brief Minimum active input time for valid click event, in milliseconds
- Input shall be in active state (after debounce) at least this amount of time to even consider
- the potential valid click event. Set the value to
0 to disable this feature
/
uint16_t time_click_pressed_min; /!< Minimum pressed time for valid click event */
/**
- \brief Maximum active input time for valid click event, in milliseconds
- Input shall be pressed at most this amount of time to still trigger valid click.
- Set to
-1 to allow any time triggering click event.
- When input is active for more than the configured time, click even is not detected and is
- ignored.
/
uint16_t time_click_pressed_max; /!< Maximum pressed time for valid click event*/
/**
/
uint16_t time_click_multi_max; /!< Maximum time between 2 clicks to be considered consecutive
click */
/**
- \brief Keep-alive event period, in milliseconds
- When input is active, keep alive events will be sent through this period of time.
- First keep alive will be sent after input being considered
- active.
/
uint16_t time_keepalive_period; /!< Time in ms for periodic keep alive event */
/**
/
uint16_t max_consecutive; /!< Max number of consecutive clicks */
} ebtn_btn_param_t;
#define EBTN_PARAMS_INIT(_time_debounce, _time_debounce_release, _time_click_pressed_min, _time_click_pressed_max, _time_click_multi_max,
_time_keepalive_period, _max_consecutive)
{
.time_debounce = _time_debounce, .time_debounce_release = _time_debounce_release, .time_click_pressed_min = _time_click_pressed_min,
.time_click_pressed_max = _time_click_pressed_max, .time_click_multi_max = _time_click_multi_max, .time_keepalive_period = _time_keepalive_period,
.max_consecutive = _max_consecutive
}
#define EBTN_BUTTON_INIT_RAW(_key_id, _param, _mask)
{
.key_id = _key_id, .param = _param, .event_mask = _mask,
}
#define EBTN_BUTTON_INIT(_key_id, _param) EBTN_BUTTON_INIT_RAW(_key_id, _param, EBTN_EVT_MASK_ALL)
#define EBTN_BUTTON_DYN_INIT(_key_id, _param)
{
.next = NULL, .btn = EBTN_BUTTON_INIT(_key_id, _param),
}
#define EBTN_BUTTON_COMBO_INIT_RAW(_key_id, _param, _mask)
{
.comb_key = {0}, .btn = EBTN_BUTTON_INIT_RAW(_key_id, _param, _mask),
}
#define EBTN_BUTTON_COMBO_INIT(_key_id, _param)
{
.comb_key = {0}, .btn = EBTN_BUTTON_INIT(_key_id, _param),
}
#define EBTN_BUTTON_COMBO_DYN_INIT(_key_id, _param)
{
.next = NULL, .btn = EBTN_BUTTON_COMBO_INIT(_key_id, _param),
}
#define EBTN_ARRAY_SIZE(_arr) sizeof(_arr) / sizeof((_arr)[0])
/**
-
\brief Button structure
/
typedef struct ebtn_btn
{
uint16_t key_id; /!< User defined custom argument for callback function purpose /
uint8_t flags; /!< Private button flags management /
uint8_t event_mask; /!< Private button event mask management */
ebtn_time_t time_change; /*!< Time in ms when button state got changed last time after valid
debounce /
ebtn_time_t time_state_change; /!< Time in ms when button state got changed last time */
ebtn_time_t keepalive_last_time; /*!< Time in ms of last send keep alive event /
ebtn_time_t click_last_time; /!< Time in ms of last successfully detected (not sent!) click event
*/
uint16_t keepalive_cnt; /*!< Number of keep alive events sent after successful on-press
detection. Value is reset after on-release /
uint16_t click_cnt; /!< Number of consecutive clicks detected, respecting maximum timeout
between clicks */
const ebtn_btn_param_t *param;
} ebtn_btn_t;
/**
-
\brief ComboButton structure
/
typedef struct ebtn_btn_combo
{
BIT_ARRAY_DEFINE(comb_key, EBTN_MAX_KEYNUM); /!< select key index - 1 means active, 0 means inactive */
ebtn_btn_t btn;
} ebtn_btn_combo_t;
/**
/**
/**
-
\brief easy_button group structure
*/
typedef struct ebtn
{
ebtn_btn_t btns; /!< Pointer to buttons array /
uint16_t btns_cnt; /!< Number of buttons in array */
ebtn_btn_combo_t btns_combo; /!< Pointer to comb-buttons array /
uint16_t btns_combo_cnt; /!< Number of comb-buttons in array */
ebtn_btn_dyn_t btn_dyn_head; /!< Pointer to btn-dynamic list */
ebtn_btn_combo_dyn_t btn_combo_dyn_head; /!< Pointer to btn-combo-dynamic list */
ebtn_evt_fn evt_fn; /*!< Pointer to event function /
ebtn_get_state_fn get_state_fn; /!< Pointer to get state function */
BIT_ARRAY_DEFINE(old_state, EBTN_MAX_KEYNUM); /*!< Old button state - 1 means active, 0 means inactive */
} ebtn_t;
/**
- \brief Button processing function, that reads the inputs and makes actions accordingly.
- \param[in] mstime: Current system time in milliseconds
*/
void ebtn_process(ebtn_time_t mstime);
/**
- \brief Button processing function, with all button input state.
- \param[in] curr_state: Current all button input state
- \param[in] mstime: Current system time in milliseconds
*/
void ebtn_process_with_curr_state(bit_array_t *curr_state, ebtn_time_t mstime);
/**
- \brief Check if button is active.
- Active is considered when initial debounce period has been a pass.
- This is the period between on-press and on-release events.
- \param[in] btn: Button handle to check
- \return
1 if active, 0 otherwise
*/
int ebtn_is_btn_active(const ebtn_btn_t *btn);
/**
- \brief Check if button is in process.
- Used for low-power processing, indicating that the buttons are temporarily idle, and embedded systems can consider entering deep sleep.
- \param[in] btn: Button handle to check
- \return
1 if in process, 0 otherwise
*/
int ebtn_is_btn_in_process(const ebtn_btn_t *btn);
/**
- \brief Check if some button is in process.
- Used for low-power processing, indicating that the buttons are temporarily idle, and embedded systems can consider entering deep sleep.
- \return
1 if in process, 0 otherwise
*/
int ebtn_is_in_process(void);
/**
- \brief Initialize button manager
- \param[in] btns: Array of buttons to process
- \param[in] btns_cnt: Number of buttons to process
- \param[in] btns_combo: Array of combo-buttons to process
- \param[in] btns_combo_cnt: Number of combo-buttons to process
- \param[in] get_state_fn: Pointer to function providing button state on demand.
- \param[in] evt_fn: Button event function callback
- \return
1 on success, 0 otherwise
*/
int ebtn_init(ebtn_btn_t *btns, uint16_t btns_cnt, ebtn_btn_combo_t *btns_combo, uint16_t btns_combo_cnt, ebtn_get_state_fn get_state_fn, ebtn_evt_fn evt_fn);
/**
- @brief Register a dynamic button
- @param button: Dynamic button structure instance
- \return
1 on success, 0 otherwise
*/
int ebtn_register(ebtn_btn_dyn_t *button);
/**
- \brief Register a dynamic combo-button
- \param[in] button: Dynamic combo-button structure instance
- \return
1 on success, 0 otherwise
*/
int ebtn_combo_register(ebtn_btn_combo_dyn_t *button);
/**
- \brief Get the current total button cnt
- \return size of button.
*/
int ebtn_get_total_btn_cnt(void);
/**
- \brief Get the internal key_idx of the key_id
- \param[in] key_id: key_id
- \return '-1' on error, other is key_idx
*/
int ebtn_get_btn_index_by_key_id(uint16_t key_id);
/**
- \brief Get the internal btn instance of the key_id, here is the button instance, and what is dynamically registered is also to obtain its button
- instance
- \param[in] key_id: key_id
- \return 'NULL' on error, other is button instance
*/
ebtn_btn_t *ebtn_get_btn_by_key_id(uint16_t key_id);
/**
- \brief Get the internal key_idx of the button
- \param[in] btn: Button
- \return '-1' on error, other is key_idx
*/
int ebtn_get_btn_index_by_btn(ebtn_btn_t *btn);
/**
- \brief Get the internal key_idx of the dynamic button
- \param[in] btn: Button
- \return '-1' on error, other is key_idx
*/
int ebtn_get_btn_index_by_btn_dyn(ebtn_btn_dyn_t *btn);
/**
- \brief Bind combo-button key with key_idx
- \param[in] btn: Combo Button
- \param[in] idx: key_idx
*/
void ebtn_combo_btn_add_btn_by_idx(ebtn_btn_combo_t *btn, int idx);
/**
- \brief Remove combo-button key with key_idx
- \param[in] btn: Combo Button
- \param[in] idx: key_idx
*/
void ebtn_combo_btn_remove_btn_by_idx(ebtn_btn_combo_t *btn, int idx);
/**
- \brief Bind combo-button key with key_id, make sure key_id(button) is already register.
- \param[in] btn: Combo Button
- \param[in] key_id: key_id
*/
void ebtn_combo_btn_add_btn(ebtn_btn_combo_t *btn, uint16_t key_id);
/**
- \brief Remove combo-button key with key_id, make sure key_id(button) is already
- register. \param[in] btn: Combo Button \param[in] key_id: key_id
*/
void ebtn_combo_btn_remove_btn(ebtn_btn_combo_t *btn, uint16_t key_id);
/**
- \brief Get keep alive period for specific button
- \param[in] btn: Button instance to get keep alive period for
- \return Keep alive period in
ms
*/
#define ebtn_keepalive_get_period(btn) ((btn)->time_keepalive_period)
/**
/**
- \brief Get number of keep alive counts for specific required time in milliseconds.
-
It will calculate number of keepalive ticks specific button shall make,
-
before requested time is reached.
- Result of the function can be used with \ref ebtn_keepalive_get_count which returns
- actual number of keep alive counts since last on-press event of the button.
- \note Value is always integer aligned, with granularity of one keepalive time period
- \note Implemented as macro, as it may be optimized by compiler when static keep alive
- is used
- \param[in] btn: Button to use for check
- \param[in] ms_time: Time in ms to calculate number of keep alive counts
- \return Number of keep alive counts
*/
#define ebtn_keepalive_get_count_for_time(btn, ms_time) ((ms_time) / ebtn_keepalive_get_period(btn))
/**
- \brief Get number of consecutive click events on a button
- \param[in] btn: Button instance to get number of clicks
- \return Number of consecutive clicks on a button
*/
#define ebtn_click_get_count(btn) ((btn)->click_cnt)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _EBTN_H */
#include <string.h>
#include "ebtn.h"
#define EBTN_FLAG_ONPRESS_SENT ((uint8_t)0x01) /*!< Flag indicates that on-press event has been sent /
#define EBTN_FLAG_IN_PROCESS ((uint8_t)0x02) /!< Flag indicates that button in process */
/* Default button group instance */
static ebtn_t ebtn_default;
/**
-
\brief Process the button information and state
-
\param[in] btn: Button instance to process
-
\param[in] old_state: old state
-
\param[in] new_state: new state
-
\param[in] mstime: Current milliseconds system time
*/
static void prv_process_btn(ebtn_btn_t *btn, uint8_t old_state, uint8_t new_state, ebtn_time_t mstime)
{
ebtn_t *ebtobj = &ebtn_default;
/* Check params set or not. */
if (btn->param == NULL)
{
return;
}
/* Button state has just changed */
if (new_state != old_state)
{
btn->time_state_change = mstime;
if (new_state)
{
btn->flags |= EBTN_FLAG_IN_PROCESS;
}
}
/* Button is still pressed /
if (new_state)
{
/
- Handle debounce and send on-press event
- This is when we detect valid press
/
if (!(btn->flags & EBTN_FLAG_ONPRESS_SENT))
{
/
- Run if statement when:
-
- Runtime mode is enabled -> user sets its own config for debounce
-
- Config debounce time for press is more than
0
/
if (ebtn_timer_sub(mstime, btn->time_state_change) >= btn->param->time_debounce)
{
/
- Check mutlti click limit reach or not.
*/
if ((btn->click_cnt > 0) && (ebtn_timer_sub(mstime, btn->click_last_time) >= btn->param->time_click_multi_max))
{
if (btn->event_mask & EBTN_EVT_MASK_ONCLICK)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONCLICK);
}
btn->click_cnt = 0;
}
btn->keepalive_last_time = mstime;
btn->keepalive_cnt = 0;
btn->flags |= EBTN_FLAG_ONPRESS_SENT;
if (btn->event_mask & EBTN_EVT_MASK_ONPRESS)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONPRESS);
}
btn->time_change = mstime;
}
}
else
{
while ((btn->param->time_keepalive_period > 0) && (ebtn_timer_sub(mstime, btn->keepalive_last_time) >= btn->param->time_keepalive_period))
{
btn->keepalive_last_time += btn->param->time_keepalive_period;
++btn->keepalive_cnt;
if (btn->event_mask & EBTN_EVT_MASK_KEEPALIVE)
{
ebtobj->evt_fn(btn, EBTN_EVT_KEEPALIVE);
}
}
if ((btn->click_cnt > 0) && (ebtn_timer_sub(mstime, btn->time_change) > btn->param->time_click_pressed_max))
{
if (btn->event_mask & EBTN_EVT_MASK_ONCLICK)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONCLICK);
}
btn->click_cnt = 0;
}
}
}
/* Button is still released /
else
{
/
- We only need to react if on-press event has even been started.
- Do nothing if that was not the case
/
if (btn->flags & EBTN_FLAG_ONPRESS_SENT)
{
/
- Run if statement when:
-
- Runtime mode is enabled -> user sets its own config for debounce
-
- Config debounce time for release is more than
0
/
if (ebtn_timer_sub(mstime, btn->time_state_change) >= btn->param->time_debounce_release)
{
/ Handle on-release event */
btn->flags &= ~EBTN_FLAG_ONPRESS_SENT;
if (btn->event_mask & EBTN_EVT_MASK_ONRELEASE)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONRELEASE);
}
if (ebtn_timer_sub(mstime, btn->time_change) >= btn->param->time_click_pressed_min &&
ebtn_timer_sub(mstime, btn->time_change) <= btn->param->time_click_pressed_max)
{
++btn->click_cnt;
btn->click_last_time = mstime;
}
else
{
if ((btn->click_cnt > 0) && (ebtn_timer_sub(mstime, btn->time_change) < btn->param->time_click_pressed_min))
{
if (btn->event_mask & EBTN_EVT_MASK_ONCLICK)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONCLICK);
}
}
btn->click_cnt = 0;
}
if ((btn->click_cnt > 0) && (btn->click_cnt == btn->param->max_consecutive))
{
if (btn->event_mask & EBTN_EVT_MASK_ONCLICK)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONCLICK);
}
btn->click_cnt = 0;
}
btn->time_change = mstime;
}
}
else
{
if (btn->click_cnt > 0)
{
if (ebtn_timer_sub(mstime, btn->click_last_time) >= btn->param->time_click_multi_max)
{
if (btn->event_mask & EBTN_EVT_MASK_ONCLICK)
{
ebtobj->evt_fn(btn, EBTN_EVT_ONCLICK);
}
btn->click_cnt = 0;
}
}
else
{
if (btn->flags & EBTN_FLAG_IN_PROCESS)
{
btn->flags &= ~EBTN_FLAG_IN_PROCESS;
}
}
}
}
}
int ebtn_init(ebtn_btn_t *btns, uint16_t btns_cnt, ebtn_btn_combo_t *btns_combo, uint16_t btns_combo_cnt, ebtn_get_state_fn get_state_fn, ebtn_evt_fn evt_fn)
{
ebtn_t *ebtobj = &ebtn_default;
if (evt_fn == NULL || get_state_fn == NULL
)
{
return 0;
}
memset(ebtobj, 0x00, sizeof(*ebtobj));
ebtobj->btns = btns;
ebtobj->btns_cnt = btns_cnt;
ebtobj->btns_combo = btns_combo;
ebtobj->btns_combo_cnt = btns_combo_cnt;
ebtobj->evt_fn = evt_fn;
ebtobj->get_state_fn = get_state_fn;
return 1;
}
/**
-
\brief Get all button state with get_state_fn.
-
\param[out] state_array: store the button state
*/
static void ebtn_get_current_state(bit_array_t *state_array)
{
ebtn_t *ebtobj = &ebtn_default;
ebtn_btn_dyn_t *target;
int i;
/* Process all buttons /
for (i = 0; i < ebtobj->btns_cnt; ++i)
{
/ Get button state */
uint8_t new_state = ebtobj->get_state_fn(&ebtobj->btns[i]);
// save state
bit_array_assign(state_array, i, new_state);
}
for (target = ebtobj->btn_dyn_head, i = ebtobj->btns_cnt; target; target = target->next, i++)
{
/* Get button state */
uint8_t new_state = ebtobj->get_state_fn(&target->btn);
bit_array_assign(state_array, i, new_state);
}
}
/**
- \brief Process the button state
- \param[in] btn: Button instance to process
- \param[in] old_state: all button old state
- \param[in] curr_state: all button current state
- \param[in] idx: Button internal key_idx
- \param[in] mstime: Current milliseconds system time
*/
static void ebtn_process_btn(ebtn_btn_t *btn, bit_array_t *old_state, bit_array_t *curr_state, int idx, ebtn_time_t mstime)
{
prv_process_btn(btn, bit_array_get(old_state, idx), bit_array_get(curr_state, idx), mstime);
}
/**
-
\brief Process the combo-button state
-
\param[in] btn: Button instance to process
-
\param[in] old_state: all button old state
-
\param[in] curr_state: all button current state
-
\param[in] comb_key: Combo key
-
\param[in] mstime: Current milliseconds system time
*/
static void ebtn_process_btn_combo(ebtn_btn_t *btn, bit_array_t *old_state, bit_array_t *curr_state, bit_array_t *comb_key, ebtn_time_t mstime)
{
BIT_ARRAY_DEFINE(tmp_data, EBTN_MAX_KEYNUM) = {0};
if (bit_array_num_bits_set(comb_key, EBTN_MAX_KEYNUM) == 0)
{
return;
}
bit_array_and(tmp_data, curr_state, comb_key, EBTN_MAX_KEYNUM);
uint8_t curr = bit_array_cmp(tmp_data, comb_key, EBTN_MAX_KEYNUM) == 0;
bit_array_and(tmp_data, old_state, comb_key, EBTN_MAX_KEYNUM);
uint8_t old = bit_array_cmp(tmp_data, comb_key, EBTN_MAX_KEYNUM) == 0;
prv_process_btn(btn, old, curr, mstime);
}
void ebtn_process_with_curr_state(bit_array_t *curr_state, ebtn_time_t mstime)
{
ebtn_t *ebtobj = &ebtn_default;
ebtn_btn_dyn_t *target;
ebtn_btn_combo_dyn_t *target_combo;
int i;
for (i = 0; i < ebtobj->btns_cnt; ++i)
{
ebtn_process_btn(&ebtobj->btns[i], ebtobj->old_state, curr_state, i, mstime);
}
for (target = ebtobj->btn_dyn_head, i = ebtobj->btns_cnt; target; target = target->next, i++)
{
ebtn_process_btn(&target->btn, ebtobj->old_state, curr_state, i, mstime);
}
for (i = 0; i < ebtobj->btns_combo_cnt; ++i)
{
ebtn_process_btn_combo(&ebtobj->btns_combo[i].btn, ebtobj->old_state, curr_state, ebtobj->btns_combo[i].comb_key, mstime);
}
for (target_combo = ebtobj->btn_combo_dyn_head; target_combo; target_combo = target_combo->next)
{
ebtn_process_btn_combo(&target_combo->btn.btn, ebtobj->old_state, curr_state, target_combo->btn.comb_key, mstime);
}
bit_array_copy_all(ebtobj->old_state, curr_state, EBTN_MAX_KEYNUM);
}
void ebtn_process(ebtn_time_t mstime)
{
BIT_ARRAY_DEFINE(curr_state, EBTN_MAX_KEYNUM) = {0};
ebtn_get_current_state(curr_state);
ebtn_process_with_curr_state(curr_state, mstime);
}
int ebtn_get_total_btn_cnt(void)
{
ebtn_t *ebtobj = &ebtn_default;
int total_cnt = 0;
ebtn_btn_dyn_t *curr = ebtobj->btn_dyn_head;
total_cnt += ebtobj->btns_cnt;
while (curr)
{
total_cnt++;
curr = curr->next;
}
return total_cnt;
}
int ebtn_get_btn_index_by_key_id(uint16_t key_id)
{
ebtn_t *ebtobj = &ebtn_default;
int i = 0;
ebtn_btn_dyn_t *target;
for (i = 0; i < ebtobj->btns_cnt; ++i)
{
if (ebtobj->btns[i].key_id == key_id)
{
return i;
}
}
for (target = ebtobj->btn_dyn_head, i = ebtobj->btns_cnt; target; target = target->next, i++)
{
if (target->btn.key_id == key_id)
{
return i;
}
}
return -1;
}
ebtn_btn_t *ebtn_get_btn_by_key_id(uint16_t key_id)
{
ebtn_t *ebtobj = &ebtn_default;
int i = 0;
ebtn_btn_dyn_t *target;
for (i = 0; i < ebtobj->btns_cnt; ++i)
{
if (ebtobj->btns[i].key_id == key_id)
{
return &ebtobj->btns[i];
}
}
for (target = ebtobj->btn_dyn_head, i = ebtobj->btns_cnt; target; target = target->next, i++)
{
if (target->btn.key_id == key_id)
{
return &target->btn;
}
}
return NULL;
}
int ebtn_get_btn_index_by_btn(ebtn_btn_t *btn)
{
return ebtn_get_btn_index_by_key_id(btn->key_id);
}
int ebtn_get_btn_index_by_btn_dyn(ebtn_btn_dyn_t *btn)
{
return ebtn_get_btn_index_by_key_id(btn->btn.key_id);
}
void ebtn_combo_btn_add_btn_by_idx(ebtn_btn_combo_t *btn, int idx)
{
bit_array_set(btn->comb_key, idx);
}
void ebtn_combo_btn_remove_btn_by_idx(ebtn_btn_combo_t *btn, int idx)
{
bit_array_clear(btn->comb_key, idx);
}
void ebtn_combo_btn_add_btn(ebtn_btn_combo_t *btn, uint16_t key_id)
{
int idx = ebtn_get_btn_index_by_key_id(key_id);
if (idx < 0)
{
return;
}
ebtn_combo_btn_add_btn_by_idx(btn, idx);
}
void ebtn_combo_btn_remove_btn(ebtn_btn_combo_t *btn, uint16_t key_id)
{
int idx = ebtn_get_btn_index_by_key_id(key_id);
if (idx < 0)
{
return;
}
ebtn_combo_btn_remove_btn_by_idx(btn, idx);
}
int ebtn_is_btn_active(const ebtn_btn_t *btn)
{
return btn != NULL && (btn->flags & EBTN_FLAG_ONPRESS_SENT);
}
int ebtn_is_btn_in_process(const ebtn_btn_t *btn)
{
return btn != NULL && (btn->flags & EBTN_FLAG_IN_PROCESS);
}
int ebtn_is_in_process(void)
{
ebtn_t *ebtobj = &ebtn_default;
ebtn_btn_dyn_t *target;
ebtn_btn_combo_dyn_t *target_combo;
int i;
for (i = 0; i < ebtobj->btns_cnt; ++i)
{
if (ebtn_is_btn_in_process(&ebtobj->btns[i]))
{
return 1;
}
}
for (target = ebtobj->btn_dyn_head, i = ebtobj->btns_cnt; target; target = target->next, i++)
{
if (ebtn_is_btn_in_process(&target->btn))
{
return 1;
}
}
for (i = 0; i < ebtobj->btns_combo_cnt; ++i)
{
if (ebtn_is_btn_in_process(&ebtobj->btns_combo[i].btn))
{
return 1;
}
}
for (target_combo = ebtobj->btn_combo_dyn_head; target_combo; target_combo = target_combo->next)
{
if (ebtn_is_btn_in_process(&target_combo->btn.btn))
{
return 1;
}
}
return 0;
}
int ebtn_register(ebtn_btn_dyn_t *button)
{
ebtn_t *ebtobj = &ebtn_default;
ebtn_btn_dyn_t *curr = ebtobj->btn_dyn_head;
ebtn_btn_dyn_t *last = NULL;
if (!button)
{
return 0;
}
if (ebtn_get_total_btn_cnt() >= EBTN_MAX_KEYNUM)
{
return 0;
}
if (curr == NULL)
{
ebtobj->btn_dyn_head = button;
return 1;
}
while (curr)
{
if (curr == button)
{
return 0;
}
last = curr;
curr = curr->next;
}
last->next = button;
return 1;
}
int ebtn_combo_register(ebtn_btn_combo_dyn_t *button)
{
ebtn_t *ebtobj = &ebtn_default;
ebtn_btn_combo_dyn_t *curr = ebtobj->btn_combo_dyn_head;
ebtn_btn_combo_dyn_t *last = NULL;
if (!button)
{
return 0;
}
if (curr == NULL)
{
ebtobj->btn_combo_dyn_head = button;
return 1;
}
while (curr)
{
if (curr == button)
{
return 0;
}
last = curr;
curr = curr->next;
}
last->next = button;
return 1;
}
主要功能函数
#include "hal_data.h"
#include "usart9.h"
#include "RTT.h"
#include "led.h"
#include <stdio.h>
#include <stdlib.h>
#include "coremark.h"
#include "ebtn_app.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
void coremark_main(void);
volatile uint8_t button_count = 0;
/*******************************************************************************************************************//**
-
main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
-
is called by main() when no RTOS is used.
*********************************************************************************************************************/
void hal_entry(void)
{
/ TODO: add your own code here */
UART9_Init();
hal_systick_init();
ebtn_APP_Key_INIT();
printf("\r\n欢迎来到瑞萨电子\r\n");
printf("很高兴试用RA4L1开发板********\r\n");
printf("串口输出打印 波特率115200\r\n\r\n");
// printf("瑞萨RA4L1 开发板 coremark跑分测试:\r\n\r\n");
// coremark_main();
while (1)
{
switch(button_count)
{
case 1:
LED1_LED2_ON();
printf("LED1 LED2 同时亮\r\n");
break;
case 2:
LED1_LED2_1();
printf("LED1先亮200ms 熄灭 然后LED2亮200ms 熄灭 重复\r\n");
break;
case 3:
LED1_LED2_2();
printf("LED1 LED2同时亮200ms 熄灭200ms 重复\r\n");
break;
case 4:
led_1_flicker();
printf("led1闪烁\r\n");
break;
case 5:
led_2_flicker();
printf("led2闪烁\r\n");
break;
case 6:
led_3_flicker();
printf("led3闪烁\r\n");
break;
default:
LED1_LED2_OFF();
break;
}
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
/*******************************************************************************************************************//**
-
This function is called at various points during the startup process. This implementation uses the event that is
-
called right before main() to set up the pins.
-
@param[in] event Where at in the start up process the code is currently at
**********************************************************************************************************************/
void R_BSP_WarmStart (bsp_warm_start_event_t event)
{
if (BSP_WARM_START_RESET == event)
{
#if BSP_FEATURE_FLASH_LP_VERSION != 0
R_FACI_LP->DFLCTL = 1U;
#endif
}
if (BSP_WARM_START_POST_C == event)
{
R_IOPORT_Open(&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
#if BSP_CFG_SDRAM_ENABLED
R_BSP_SdramInit(true);
#endif
}
}
#if BSP_TZ_SECURE_BUILD
FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();
/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{
}
FSP_CPP_FOOTER
#endif



根据button_count标志位来进行点灯操作
详情请看视频讲解,非常的详细!!!!!

该按键库实现了单个按键的单击,双击,三击,长按1,长按2,长按3,只要你想的到的,都可以扩展!!!