the following article is a simple implement of:
1. long press with customized interval
2. short- multi press
3. the hurried pressings might lead system crash, it needs protection, so I ingore any-button signal in the next 4 seconds
BUTTON 1 implemented to measure the pressing time (in 0.1 sec)
BUTTON 2 implemented for receiving double press
SDK 11/ nRF51822
*about how to start your UART, please read this article
STEP 1 . add ..\..\..\..\..\..\components\libraries\gpiote
add these two files to your project
STEP 2. add button definition
add the code about line 58.
#include "app_button.h" #include "app_gpiote.h" #define BUTTON_DEBOUNCE_DELAY 10 #define APP_GPIOTE_MAX_USERS 1 .
STEP 3. buttons initialization
change func buttons_leds_init( ) like this
static void buttons_leds_init(bool * p_erase_bonds) { bsp_event_t startup_event; uint32_t err_code = bsp_init(BSP_INIT_NONE, APP_TIMER_TICKS(30, APP_TIMER_PRESCALER), bsp_event_handler); APP_ERROR_CHECK(err_code); static app_button_cfg_t p_button[] = {{BUTTON_1, APP_BUTTON_ACTIVE_LOW, NRF_GPIO_PIN_PULLUP, button_handler}, {BUTTON_2, APP_BUTTON_ACTIVE_LOW, NRF_GPIO_PIN_PULLUP, button_handler},}; APP_GPIOTE_INIT(APP_GPIOTE_MAX_USERS); // Initializing the buttons. err_code = app_button_init(p_button, sizeof(p_button) / sizeof(p_button[0]), BUTTON_DEBOUNCE_DELAY); APP_ERROR_CHECK(err_code); err_code = app_button_enable(); APP_ERROR_CHECK(err_code); err_code = bsp_btn_ble_init(NULL, &startup_event); APP_ERROR_CHECK(err_code); *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); }
add button_handler( ) above buttons_leds_init ( )
static void button_handler(uint8_t pin_no, uint8_t button_action) { uint32_t err_code; if (false != is_able_to_receiving_button_pressed_signal) { if(button_action == APP_BUTTON_PUSH) { switch(pin_no) { case BUTTON_1: PRINTF_MSG("press button 1 \r\n"); err_code = app_timer_start(measure_pressed_time_timer_id,PRESS_MEASURE_INTERVAL, NULL); APP_ERROR_CHECK(err_code); break; case BUTTON_2: if (0 == button2_press_count) { err_code = app_timer_start(double_press_id,DOUBLE_PRESS_READ_INTERVAL, NULL); APP_ERROR_CHECK(err_code); } break; default: break; } } else if (button_action == APP_BUTTON_RELEASE) { switch(pin_no) { case BUTTON_1: PRINTF_MSG("button 1 release\r\n"); uint32_t err_code; err_code = app_timer_stop(measure_pressed_time_timer_id); APP_ERROR_CHECK(err_code); printf("**button1_measured_count= %f totally**\r\n",button1_measured_count*0.1); button1_measured_count= 0; is_able_to_receiving_button_pressed_signal= false; app_timer_start(button_restrict_id,BUTTON_RESTRICT_INTERVAL, NULL); break; case BUTTON_2: //PRINTF_MSG("button 2 release\r\n"); button2_press_count= button2_press_count+1; if (DOUBLE_PRESS == button2_press_count) { is_able_to_receiving_button_pressed_signal = false; printf("detect double press !!\r\n"); app_timer_start(button_restrict_id,BUTTON_RESTRICT_INTERVAL, NULL); } break; case BUTTON_3: break; default: break; } } } }
STEP 4. create timers
add the code about line.120
static uint16_t button1_measured_count= 0; APP_TIMER_DEF(measure_pressed_time_timer_id); #define PRESS_MEASURE_INTERVAL APP_TIMER_TICKS(100, APP_TIMER_PRESCALER) static uint8_t button2_press_count; APP_TIMER_DEF(double_press_id); #define DOUBLE_PRESS_READ_INTERVAL APP_TIMER_TICKS(1500, APP_TIMER_PRESCALER) #define DOUBLE_PRESS (0x02) static bool is_able_to_receiving_button_pressed_signal= true;
APP_TIMER_DEF(button_restrict_id); #define BUTTON_RESTRICT_INTERVAL APP_TIMER_TICKS(4000, APP_TIMER_PRESCALER)
add the code in timer_init ( )
uint32_t err_code;
err_code = app_timer_create(&measure_pressed_time_timer_id,
APP_TIMER_MODE_REPEATED,
button1_triggered_event_handler);
APP_ERROR_CHECK(err_code);
err_code = app_timer_create(&double_press_id,
APP_TIMER_MODE_SINGLE_SHOT,
button2_triggered_event_handler);
APP_ERROR_CHECK(err_code);
err_code = app_timer_create(&button_restrict_id,
APP_TIMER_MODE_SINGLE_SHOT,
button_restrict_handler);
APP_ERROR_CHECK(err_code);
about the variable"is_able_to_receiving_button_pressed_signal ":
once the variable is_able_to_receiving_button_pressed_signal becomes false, the button pressed would be ignore, it will prevent system from crash of busy interruption.
add the code above timer_init ( )
static void button1_triggered_event_handler(void * p_context) { UNUSED_PARAMETER(p_context); button1_measured_count++; printf("recent counter = %f\r\n",button1_measured_count*0.1); } static void button2_triggered_event_handler(void * p_context) { UNUSED_PARAMETER(p_context); uint32_t err_code; printf("button2_press_count= %d\r\n",button2_press_count); button2_press_count= 0; } static void button_restrict_handler(void * p_context) { UNUSED_PARAMETER(p_context); is_able_to_receiving_button_pressed_signal = true; printf("can received button\r\n"); }
program and upload to your device.
STEP 5.Test
I long press button 1 for 10 sec then rapidly press button 2
the device can count how long I press button 1 and only receive 2 press of button 2
like this:
Reference:
https://github.com/NordicSemiconductor/nrf51-app-button-example/blob/master/main.c