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

Using more than 4 buttons with GPIOTE interrupts

Hi,

I am using GPIOTE interrupts to detect button presses. It works fine but there are only four channels in GPIOTE->EVENTS_IN[] and each channel can only be assigned to one pin. How should I do if I want to implement more than 4 buttons?

Basically I set up GPIOTE like this:

  pinInput(pin); // make sure the pin is set as input
  NRF_GPIOTE->CONFIG[channel] = (static_cast<uint32_t>(transitionMode) << GPIOTE_CONFIG_POLARITY_Pos) |
      (pin << GPIOTE_CONFIG_PSEL_Pos) |
      (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
  NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << channel; // @warning: we should use bitfields instead
  NRF_GPIOTE->EVENTS_IN[channel] = 0;

and in the GPIOTE_IRQHandler I check which channel has been interrupted and send an appropriate callback.

I do not use any sd by the way.

Thanks!

Parents
  • Hi Aryan,

    Thanks for your reply. I tried using port but I am having som problems with it. In my test program I want to use one button to toggle a green LED. In a while loop a red LED is blinking. When I press the button the green LED is not toggled and the red LED stops blinking, I interpret that as that the program is stuck somewhere. I can't figure out why this does not work. Can you see the problem in my code?

    void GPIOTE_IRQHandler(void) {
      // If PORT event has been called, clear event and toggle LED
      if (NRF_GPIOTE->EVENTS_PORT) {
        NRF_GPIOTE->EVENTS_PORT = 0;
    
        pinToggle(LED_GREEN);
      }
    }
    
    int main() {
      setupLEDPins();
    
      // Set Menu button as input
      nrf_gpio_cfg_input(BUTTON_MENU_PIN, NRF_GPIO_PIN_NOPULL);
    
      // Enable sense on the Menu button
      nrf_gpio_cfg_sense_input(BUTTON_MENU_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
    
      // Set the GPIOTE PORT event as interrupt source
      NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
    
      // Enable interrupts for GPIOTE
      NVIC_EnableIRQ(GPIOTE_IRQn);
    
      // Toggle red LED to show life sign
      while (1) {
        pinToggle(LED_RED);
        delayMs(100);
      }
      return 0;
    }
    
  • Hi Aryan, yes, that is basically all code. Made some modifications and used nrf_gpio_cfg_output and nrf_gpio_pin_toggle instead of my own gpio functions and added

    NVIC_ClearPendingIRQ(GPIOTE_IRQn); NVIC_SetPriority(GPIOTE_IRQn, 3);

    before NCIV_EnableIRQ(GPIOTE_IRQn);

    but I still get the same result. I am not using APP_ERROR_CHECK or any softdevice.

    I also have a hard time understanding how it can get stuck. I read that SENSE is used to wake up the nrf, could it be that it does something to the power state of the CPU? Or could it be that the interrupt is called continuously of some reason blocking the execution of the program?

    Can you recommend any good examples where the PORT event is used to read buttons?

    Thanks!

Reply
  • Hi Aryan, yes, that is basically all code. Made some modifications and used nrf_gpio_cfg_output and nrf_gpio_pin_toggle instead of my own gpio functions and added

    NVIC_ClearPendingIRQ(GPIOTE_IRQn); NVIC_SetPriority(GPIOTE_IRQn, 3);

    before NCIV_EnableIRQ(GPIOTE_IRQn);

    but I still get the same result. I am not using APP_ERROR_CHECK or any softdevice.

    I also have a hard time understanding how it can get stuck. I read that SENSE is used to wake up the nrf, could it be that it does something to the power state of the CPU? Or could it be that the interrupt is called continuously of some reason blocking the execution of the program?

    Can you recommend any good examples where the PORT event is used to read buttons?

    Thanks!

Children
No Data
Related