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

What's the maximum frequency for a Pin event on rising edge or falling edge ?

Hello everyone,

I generate an interruption when an rising edge is detected on one of my I/O.

It seems that the interruption doesn't trigger correctly for an input frequency higher than 40 kHz. In fact, when I have an input signal as an example of 70 kHz the frequency on which the interrupt is launch is blocking to 40 kHz.

is it due to the limitation of the system ? It seems to be incredible for a 64 Mhz clock ...

Best regards,

Sylvain.

#include <stdbool.h>
#include "nrf.h"
#include "nrf_drv_gpiote.h"
#include "app_error.h"
#include "boards.h"
#include "nrf_drv_timer.h"

#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "app_util_platform.h"


#define PIN_IN 33 //BUTTON_1 

#define PIN_OUT BSP_LED_0

const nrf_drv_timer_t TIMER = NRF_DRV_TIMER_INSTANCE(1);
uint8_t state = 0, state_prev=0;
uint8_t ready = 0;
uint16_t captured_value,captured_prev = 0;
float frequency = 0.0;

void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    nrf_drv_gpiote_out_toggle (34);
}

void timer_event_handler(nrf_timer_event_t event_type, void* p_context)
{
 //Never launch, do nothing
}

/**
 * @brief Function for configuring: input PIN, output PIN,
 * and configures GPIOTE to give an interrupt on pin change.
 */
static void gpio_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);
    
    /* Configure output pin */
    nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);
    
    err_code = nrf_drv_gpiote_out_init(PIN_OUT, &out_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_gpiote_out_init(34, &out_config); //Output on P1.02 for debugging
    APP_ERROR_CHECK(err_code);
    /**************************************/

    /* Configure input for capture */
    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(PIN_IN, true);
    /**************************************/
}

static void timer_init (void){
    
    ret_code_t err_code;

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init (&TIMER, &timer_cfg, timer_event_handler);
    APP_ERROR_CHECK(err_code);
}

int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("HelloWorld");

    /*Macro for processing all log entries from the buffer.
    It blocks until all buffered entries are processed by the backend.*/
    NRF_LOG_FLUSH();
        
    timer_init();
    gpio_init();
    
    nrf_drv_timer_enable(&TIMER);
    
    while (true)
    {
        //Nothing to do as it's the first test
    }
}

/** @} */

  • Hi Edvin,

    Working on two different type of edges can't work because of the duty cycle of the signal different that 50% ...

    That's seems complicate to do with PPI ... Maybe, even if it's ressource consuming, there could be a solution with two different timer. One of the timer could measure the high state and the other one could measure the low state. I'm reflecting about that ..

    Honestly, I don't test your code from your previous reply because I'm not familiar with this type of C (I'm coming from Atmel Studio) that's why I use the driver... Maybe there're resources to explain this type of code ?

    You tell me that I need to use two GPIOTE events but I was thinking that only one GPIOTE event can be assign per pin ?


    Kind regards,
    Sylvain.

  • Hello,

    It does not matter if the duty cycle is more or less than 50%. 

    Either, your PWM signal (pulse width modulation) is active low, or active high. I assume now that it is active high, but if it is not, just swap the rising and falling triggers/events.

     

    your signal:

                      --------------------_____________________--------------------_____________________

                      High                   Low                                      High                Low

                      <----------------->                                          <---------------------------------------------------->

                         Duty cycle                                                       Period

     

    Start the timer.

    on rising edge (LoToHi), clear the timer. The timer will still run, but it will be reset to start at 0.

    on falling edge, capture the time. this is how many ticks that the signal is high.

    on rising edge capture the time again (on a different capture register). and reset clear the timer again.

     

    This will give you two values. the time that the signal is high, and the time between two times the signal is high. That is your duty cycle and your period, respectively. It does not matter whether the duty cycle is more or less than 50% of the period.

    You can have several GPIOTE events for one pin. Unfortunately, there are no documentation on how to write the code to use these registers. But you have pretty much everything you need. 

    If you use an IDE, you can go to the definitions for the different commands, and see what options that you have.

    You can also look into the ppi example in the sdk. It uses a driver, but if you click through the functions in main, you will see how the driver is used.

    The example is located in SDK\examples\peripheral\ppi

     

     

    Best regards,

    Edvin

  • Edvin,

    Thank you for the support, you enlighted me on a lot of points.

    Sincerely,
    Sylvain

  • Glad I could help. Let me know if you encounter any more problems with the PPI.

     

    Best regards,

    Edvin

Related