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

How to Read status of gpio(pin 12) whether it is high or low?

I am getting confused when using nrf_gpio_cfg_input(PIN_12,NRF_GPIO_PIN_PULLDOWN) should i keep it as NRF_GPIO_PIN_PULLDOWN,PULLUP or should i use NRF_GPIO_PIN_SENSE_HIGH. I want to connect a button to pin 12 and depending on whether it is high or low switch on an led conncted to PIN 14.

  • There are several ways of doing this. I will go through 3 of them below. If you should use a pull up or pull down depends on how the button is connected to the hardware. On the DK the button pulls the GPIO to ground, therefore you need a pull up so that the GPIO is in high state whenever the button is not pushed.

    ###GPIO

    The simplest way is to read the status of the GPIO IN register and set the LED pin accordingly. You can use the GPIO driver in the SDK for this. This will keep the CPU running all the time which will consume a lot of current and is not a good solution.

    #include "nrf_gpio.h"
    #define LED 17
    #define BTN 13
    int main(void){
        nrf_gpio_cfg_output(LED);
        nrf_gpio_cfg_input(BTN,NRF_GPIO_PIN_PULLUP);
        while (true)
        {
            if(nrf_gpio_pin_read(BTN)){
                nrf_gpio_pin_clear(LED);
            }else{
                nrf_gpio_pin_set(LED);
            }
        }
    }
    

    ###GPIOTE

    You can use the GPIOTE peripheral to sense for a transition on the button pin and use the corresponding software interrupt to toggle the LED. Here I'm using the GPIOTE driver in the SDK. This is nice if you want to do more stuff in the interrupt handler than just toggling the LED. The CPU is also sleeping while waiting for the event and consumes a minimal amount of current.

    #include "nrf_gpio.h"
    #include "nrf_drv_gpiote.h"
    #define LED 17
    #define BTN 13
    // Event handler for the GPIOTE event for toggling LED
    void button_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action){
        if(action == NRF_GPIOTE_POLARITY_TOGGLE  && pin == BTN){
            nrf_gpio_pin_toggle(LED);
        }
    }
    
    int main(void){
        // Configure LED GPIO
        nrf_gpio_cfg_output(LED);
        nrf_gpio_pin_set(LED);
        
        //Initialize GPIOTE driver
        nrf_drv_gpiote_init();
        
        //Configure button with pullup and event on both high and low transition
        nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
        config.pull = NRF_GPIO_PIN_PULLUP;
        nrf_drv_gpiote_in_init(BTN, &config, button_event_handler); //Assign button config to a GPIOTE channel
                                                                    //and assigning the interrupt handler
        nrf_drv_gpiote_in_event_enable(BTN, true);                  //Enable event and interrupt
        
        for(;;)__WFE(); //CPU sleep while waiting for event
    }
    

    ###GPIOTE and PPI

    Instead of using an interrupt handler you can toggle the LED directly using the PPI peripheral. You will need to add an additional GPIOTE channel for the LED task. And then connect the button event with the LED task using PPI. This does not use any interrupt handlers and therefore never start the CPU. Hence lower power consumption. Here I'm including the PPI driver from the SDK.

    #include "nrf_gpio.h"
    #include "nrf_drv_gpiote.h"
    #include "nrf_drv_ppi.h"
    #define LED 17
    #define BTN 13
    int main(void){
        //Initialize GPIOTE driver
        nrf_drv_gpiote_init();
        
        //Configure button with pullup and event on both high and low transition
        nrf_drv_gpiote_in_config_t btn_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
        btn_config.pull = NRF_GPIO_PIN_PULLUP;
        nrf_drv_gpiote_in_init(BTN, &btn_config, NULL); //Assign button config to a GPIOTE channel
        uint32_t btn_addr = nrf_drv_gpiote_in_event_addr_get(BTN); //Store event address from GPIOTE event
        nrf_drv_gpiote_in_event_enable(BTN, false); //Enable event
        
        //Configure LED toggle task
        nrf_drv_gpiote_out_config_t led_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        nrf_drv_gpiote_out_init(LED, &led_config); //Assign LED config to a GPIOTE channel
        uint32_t led_addr = nrf_drv_gpiote_out_task_addr_get(LED); //Store task address from GPIOTE task
        nrf_drv_gpiote_out_task_enable(LED); //Enable task
        
        //Connect GPIOTE event and task using PPI peripheral
        nrf_drv_ppi_init();
        nrf_ppi_channel_t ppi_channel = NRF_PPI_CHANNEL0;
        nrf_drv_ppi_channel_alloc(&ppi_channel);
        nrf_drv_ppi_channel_assign(ppi_channel, btn_addr, led_addr); // Connect the previously stored task and event addresses
        nrf_drv_ppi_channel_enable(ppi_channel);
            
        for(;;)__WFE(); //CPU sleep while waiting for event
    }
    
Related