NRF52810 实现按键的长按及单双击
在做nordic nrf52810的芯片的项目中要用到按键的长按以及单双击,实现的过程主要是通过库文件的一些函数,对一些要用到的函数内容进行稍加改动完成的,库文件为bsp.c文件,下面主要是实现的流程:
1.首先我们要对按键进行配置
app_button_cfg_t app_buttons[BUTTONS_NUMBER] = {{BSP_BUTTON_0,false,BUTTON_PULL,bsp_button_event_handler},};
这里只是对BUTTON0进行了配置;
2.然后实现按键的事件函数
(bsp_button_event_handler(uint8_t pin_no,uint8_t button_action)),按键中主要有三个事件:按键按下、按键释放以及长按;
(1)当按键按下时,就会开启两个定时器,一个用来判断是否为长按还是短按,另一个为判断单双击;
判断长按短按:当按键按下时,超过一秒还没有释放按键我们就认定为长按,在超时函数中设置按键为长按事件,一秒内释放认定为短按;
判断单双击:当按键按下时,在没有超时的时间内,每按下一次标志位 click_count 就加一,然后在超时函数中清零标志位,执行回调函数,最后在此按键下通过标志位的值来判断单双击。
(2)当按键释放时,要停止判断长按的定时器,然后把按键释放的事件赋值给event
(3)当按键为长按时,会把长按事件赋值给event;
最后就会执行回调函数。
下图为函数的实现过程
void bsp_button_event_handler(uint8_t pin_no,uint8_t button_action)
{
bsp_event_t event = BSP_EVENT_NOTHING;
uint32_t button = 0;
uint32_t err_code;
static uint8_t current_long_push_pin_no;
static bsp_event_t release_event_at_push[BUTTONS_NUMBER];
button = bsp_board_pin_to_button_idx(pin_no);
if(button<BUTTONS_NUMBER)
{
switch(button_action)
{
case APP_BUTTON_PUSH: //按键按下事件
if(m_events_list[button].long_push_event != BSP_EVENT_NOTHING)
{
app_timer_start(click_button_id,BUTTON_CLICK_INTERAL,NULL);//判断单双击
app_timer_start(bsp_button_id,APP_TIMER_TICKS(BSP_LONG_PUSH_TIMER),NULL);//判断长按短按
if(err_code == NRF_SUCCESS)
{
current_log_push_pin_no = pin_no;
}
click_count++;
}
break;
case APP_BUTTON_RELEASE://按键释放事件
app_timer_stop(bsp_button_id);
if(release_event_at_push[button] == m_events_list[button].release_event)
{
event = m_events_list[button].release_event;
}
break;
case BSP_BUTTON_ACTION_LONG_PUSH://长按事件
event = m_events_list[button].release_event;
release_event_at_push[button] = m_event_list[button].long_push_event;
}
}
if((event != BSP_EVENT_NOTHING) && (m_registerd_callback != NULL))
{
m_registered_callback(event); //执行回调函数
}
}
3. 修改bsp_init 函数
在bsp_init 函数中主要修改事件分配函数,使之对应不同的按键及事件;
uint32_t bsp_init(uint32_t type,bsp_event_callback_t callback)
{
uint32_t err_code = NRF_SUCCESS;
#if LEDS_NUMBER > 0 && !(defined BSP_SIMPLE)
m_indication_type = type;
#endif
#if BUTTONS_NUMBER > 0 && !(defined BSP_SIMPLE)
m_registered_callback = callback;
#endif
if(type & BSP_INIT_BUTTONS)
{
uint32_t num;
for(num=0;((num < BUTTONS_NUMBER) && (err_code == NRF_SUCCESS));num++)
{
err_code = bsp_event_to_button_action_assign1(num,BSP_BUTTON_ACTION_PUSH,BSP_EVENT_DEFAULT);//事件分配函数
err_code = bsp_event_to_button_action_assign1(num,BSP_BUTTON_ACTION_RELEASE,BSP_EVENT_DEFAULT);//事件分配函数
err_code = bsp_event_to_button_action_assign2(num,BSP_BUTTON_ACTION_LONG_PUSH,BSP_EVENT_DEFAULT);//事件分配函数
}
}
if(err_code == NRF_SUCCESS)
{
err_code = app_button_init((app_button_cfg_t*)app_buttons,BUTTONS_NUMBER,APP_TIMER_TICKS(50)); //消抖
}
if(err_code == NRF_SUCCESS)
{
err_code = app_button_enable();//使能按键
}
if(err_code == NRF_SUCCESS)
{
err_code = app_timer_create(&bsp_button_id,APP_TIMER_MODE_SINGLE_SHOT,button_timerout_handler);
}
}
uint32_t bsp_event_to_button_action_assign1(uint32_t button,bsp_button_action_t action, bsp_event_t event)
{
uint32_t err_code = NRF_SUCCESS;
#if BUTTONS_NUMBER > 0
if(button < BUTTONS_NUMBER)
{
if(event == BSP_EVENT_DEFAULT)
{
event = (bsp_event_t)(BSP_EVENT_KEY_0 + button);
}
switch(action)
{
case BSP_BUTTON_ACTION_PUSH:
m_events_list[button].push_event = event;
break;
case BSP_BUTTON_ACTION_LONG_PUSH:
m_event_list[button].long_push+event = event;
break;
case BSP_BUTTON_ACTION_RELEASE:
m_event_list[button].release_event = event;
break;
default:
err_code = NRF_ERROR_INVALID_PARAM;
break;
}
}
else
{
err_code = NRF_ERROR_INVALID_PARAM;
}
#else
err_code = NRF_ERROR_INVALID_PARAM;
#endif
return err_code;
}
BSP_EVENT_KEY_0代表按键0的短按,在函数bsp_event_to_button_action_assign2中修改BSP_EVENT_KEY_0为BSP_EVENT_KEY_C0代表按键0的长按;
这样在bsp.c文件中的函数就设置完了,接下来主要是实现一个按键的事件函数和按键的初始化
4. 初始化按键
void button_init()
{
ret_code_t err_code;
err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS,button_event_handler);
APP_ERROR_CHECK(err_code);
}
5.实现按键事件回调函数
void button_event_handler(bsp_event_t event)
{
switch((uint8_t)event)
{
case BSP_EVENT_KEY_0:
if(click_flag == 1) 单击
{...........}
else if(click_flag == 2) 双击
{............}
break;
case BSP_EVENT_KEY_C0: 长按
......
break;
}
}
这就是实现按键单双击及长按的主要流程,其中还有一些细节以及定时器超时函数中的实现内容这里没有给出,但也都提到了。