This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Reading multiple events with GPIOTE

I'm trying to test out pin change interrupts using the PCA10028 dev board. I'm using two buttons to turn off and on an LED. The code below is only generating events from button1. I'm trying to illuminate and LED when button1 is pressed and turn it off when button2 is pressed. So far, I'm only able to illuminate the LED, not turn it off. What am I missing? I'm using the nrf51422 with no SD. Thanks for the help.

static void button_gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {

if(pin & BUTTON2)//turn off led { //app_sched_event_put(NULL,0, led_clear_event); nrf_gpio_pin_set(LED_PIN1); }

else if(pin & BUTTON1) //light up led { nrf_gpio_pin_clear(LED_PIN1); //app_sched_event_put(NULL,0, led_set_event); } }

void gpiote_handler_init() { if(!nrf_drv_gpiote_is_init()) { nrf_drv_gpiote_init(); } }

void gpiote_button_init() {

nrf_drv_gpiote_in_config_t gpiote_button1 = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); gpiote_button1.pull = NRF_GPIO_PIN_PULLUP;

nrf_drv_gpiote_in_config_t gpiote_button2 = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);

gpiote_button2.pull = NRF_GPIO_PIN_PULLUP;

nrf_drv_gpiote_in_init(BUTTON1, &gpiote_button1, button_gpiote_event_handler); nrf_drv_gpiote_in_init(BUTTON2, &gpiote_button2, button_gpiote_event_handler);

nrf_drv_gpiote_in_event_enable(BUTTON1, true);

nrf_drv_gpiote_in_event_enable(BUTTON2, true);

}

/** * @brief Function for application main entry. */

int main(void) {

pin_config();

scheduler_init();

gpiote_handler_init();

gpiote_button_init();

while (true)
{ 			
app_sched_execute();	
}}
  • You know that there is app_button library available at SDKXX\components\libraries\button. When you press a button, most likely there is debounce causing un-necessary events. App_button library takes care of this debounce. Anyways, if you do not worry about the debounce then change your button handler little like below and it should work.

    static void button_gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
    
    if((pin == BUTTON2) && (NRF_GPIOTE_POLARITY_HITOLO == action))//turn off led 
    { 
    //app_sched_event_put(NULL,0, led_clear_event); 
    nrf_gpio_pin_set(LED_PIN1); 
    }
    
    else if((pin == BUTTON1) && (NRF_GPIOTE_POLARITY_HITOLO == action)) //light up led 
    { 
    nrf_gpio_pin_clear(LED_PIN1); 
    //app_sched_event_put(NULL,0, led_set_event); 
    } }
    
    void gpiote_handler_init() { 
    if(!nrf_drv_gpiote_is_init()) 
    { nrf_drv_gpiote_init(); 
    } }
    
  • I realize there is an app_button library. I don't think this is a debounce issue since I'm turning on the LED with any change on one button and turning off the LED with any change on the other button, so it isn't level dependent. I've tried the change that you suggested as well as usign NRF_GPIOTE_POLARITY_TOGGLE in my button handler. Still I can only illuminate the LED and not turn it off. Is there something I need to do to clear a port event since I'm not using high accuracy mode? I'm really stuck on this...

    static void button_gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action{

    if(pin == BUTTON2 && action == NRF_GPIOTE_POLARITY_TOGGLE)//turn off led{

    	//app_sched_event_put(NULL,0, led_clear_event);
    	nrf_gpio_pin_set(LED_PIN1);
    }
    else if(pin == BUTTON1 && action == NRF_GPIOTE_POLARITY_TOGGLE) //light up led
    {
    	nrf_gpio_pin_clear(LED_PIN1);
    	//app_sched_event_put(NULL,0, led_set_event);
    }}
    

    void gpiote_handler_init(){

    //uint32_t err_code;
    if(!nrf_drv_gpiote_is_init())
    {
    nrf_drv_gpiote_init();
    }}
    

    void gpiote_button_init(){

    nrf_drv_gpiote_in_config_t gpiote_button1 = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
    gpiote_button1.pull = NRF_GPIO_PIN_PULLUP;
    
    nrf_drv_gpiote_in_config_t gpiote_button2 = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
    gpiote_button2.pull = NRF_GPIO_PIN_PULLUP;
    
    nrf_drv_gpiote_in_init(BUTTON1, &gpiote_button1, button_gpiote_event_handler);
    nrf_drv_gpiote_in_init(BUTTON2, &gpiote_button2, button_gpiote_event_handler);
    
    nrf_drv_gpiote_in_event_enable(BUTTON1, true);
    nrf_drv_gpiote_in_event_enable(BUTTON2, true);
    

    }

  • I have tried using the app_button handler and am still seeing no success... Any ideas?

    void pin_config() { nrf_gpio_cfg_output(LED_PIN1); nrf_gpio_pin_set(LED_PIN1); nrf_gpio_cfg_input(BUTTON1, NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_input(BUTTON2, NRF_GPIO_PIN_PULLUP); }

    static void lfclk_request(void)//this is only needed when a Soft Device isn't used. { uint32_t err_code = nrf_drv_clock_init(NULL); APP_ERROR_CHECK(err_code); nrf_drv_clock_lfclk_request(); }

    static void timer_init(void) { APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, true); }

    static void button_gpiote_event_handler(uint8_t pin_no, uint8_t button_action) { if ((pin_no == BUTTON2) && (button_action == APP_BUTTON_PUSH))//turn off led { nrf_gpio_pin_set(LED_PIN1); } else if ((pin_no == BUTTON1) && (button_action == APP_BUTTON_PUSH)) //light up led { nrf_gpio_pin_clear(LED_PIN1); } }

    void button_init() { static app_button_cfg_t buttons [] = { {BUTTON1, APP_BUTTON_ACTIVE_LOW, NRF_GPIO_PIN_PULLUP, button_gpiote_event_handler}, {BUTTON2, APP_BUTTON_ACTIVE_LOW, NRF_GPIO_PIN_PULLUP, button_gpiote_event_handler}};

    app_button_init(buttons, BUTTON_COUNT, BUTTON_DEBOUNCE_DELAY);
    

    }

    /**

    • @brief Function for application main entry. */ int main(void) { pin_config(); scheduler_init(); lfclk_request(); timer_init(); APP_GPIOTE_INIT(GPIOTE_MAX_USERS);

      //gpiote_handler_init(); //gpiote_button_init(); button_init(); app_button_enable();

    // timer_start(); while (true) { app_sched_execute(); } } /** @} */

  • I found the variable #define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS in nrf_config.h, this was set to 1. When I increased this I am able to generate GPIOTE events from more pins. This solved my problem.

  • Thanks for coming back and answering your own question. Debugging and Stepping through the code to find the error source is a good way to find problems in the code :)

Related