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

measuring input GPIO pin frequency with soft device running

Hello,

is it possible to measure frequency from 1Hz up to 400kHz (50% duty cycle) on gpio pin having soft device enabled with Peripheral functionality? The measurement will be invoked on demand by the connected central device. I will use nRF51822, rev. 3, S110 or S130, SDK 8 or 9.

If this is not possible, please tell me if following scenario would be ok:

  • invoke measurement
  • disable soft device (disconnection from central)
  • manage measurement (what's the best way: which timer?, PPI? GPIOTE?)
  • enable soft device

Thank you!

btw, what is the maximum frequency that can be measure on gpio pin?

Parents
  • @Aryan, It's been a long time, however now I've already got time to deal with this frequency meter. Your advice works perfectly! After datasheet and forum reading I came up with the final code using all of these peripherals according to your scheme. PPI rulez :-) It also works with Soft Device enabled. I share my code below (not yet so beautiful..) so maybe someone would save his time on a similiar problem.

    #define FREQ_MEASURE_PIN 6
    
    static void timer_init()
    {
    	NRF_TIMER1->TASKS_STOP = 1;
    	NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
    	NRF_TIMER1->PRESCALER = 8;	// Fhck / 2^8 
    	NRF_TIMER1->CC[0] = 62500;	// 62500 - 1s
    	
    	NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);	
    	
    	NRF_TIMER1->TASKS_CLEAR = 1;
    	NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
    	
    	NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    }
    
    static void counter_init()
    {
    	NRF_TIMER2->TASKS_STOP = 1;	
    	NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter;
    	NRF_TIMER2->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
    	NRF_TIMER2->TASKS_CLEAR = 1;
    	NRF_TIMER2->EVENTS_COMPARE[0] = 0;
    }
    
    static void gpiote_init(uint32_t pin)
    {
    	NRF_GPIOTE->CONFIG[0] 	= 	0x01 << 0; 								// MODE: Event
    	NRF_GPIOTE->CONFIG[0] 	|= 	pin << 8;								// Pin number
    	NRF_GPIOTE->CONFIG[0] 	|= 	NRF_GPIOTE_POLARITY_LOTOHI	<< 16;		// Event rising edge 	
    }
    
    static void ppi_timer_stop_counter_init()
    {
    	NRF_PPI->CHEN |= 1 << 0;
    	*(&(NRF_PPI->CH0_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
    	*(&(NRF_PPI->CH0_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_STOP;
    	NRF_PPI->CHENSET |= 1 << 0;
    }
    
    static void ppi_gpiote_counter_init()
    {
    	NRF_PPI->CHEN |= 1 << 1;
    	*(&(NRF_PPI->CH1_EEP)) = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
    	*(&(NRF_PPI->CH1_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_COUNT;
    	NRF_PPI->CHENSET |= 1 << 1;
    }
    
    int main()
    {
        // Soft Device initialization..
    
       	NVIC_EnableIRQ(TIMER1_IRQn);
        NVIC_SetPriority(TIMER1_IRQn, NRF_APP_PRIORITY_LOW);	
    
        nrf_gpio_cfg_input(FREQ_MEASURE_PIN, NRF_GPIO_PIN_NOPULL);
    
    	counter_init();
    	timer_init();
    	gpiote_init(FREQ_MEASURE_PIN);
    	ppi_gpiote_counter_init();
    	ppi_timer_stop_counter_init();
    
    	NRF_TIMER1->TASKS_START = 1;
    	NRF_TIMER2->TASKS_START = 1;
    	
    	for(;;) {
    		// power manage //
    	}
    }
    
    void TIMER1_IRQHandler(void) 
    {
    	if (NRF_TIMER1->EVENTS_COMPARE[0] != 0)
    	{
    		NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    		NRF_TIMER2->TASKS_CAPTURE[0] = 1;
    				
    		LOG_INFO("cc: %dHz", NRF_TIMER2->CC[0]);
          	
    		NRF_TIMER1->TASKS_CLEAR = 1;
    		NRF_TIMER2->TASKS_CLEAR = 1;	
    						
    		NRF_TIMER2->TASKS_START = 1;			
        }
    }
    

    Thanks!

  • Hi Inspectron, Check if there are any hardfaults or other conflicts with modules used here somewhere else in your code, this code should work perfectly when used alone.

Reply Children
No Data
Related