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

Timer measurement using PPI on nRF51822

Hi All

I'm trying to measure the Ton and the Toff of a signal present on an input pin of a nRF51822.

The idea is to use PPI, Timer 1 and save timer on every falling/rising edge of the input pin into CC[3] 

I wrote a simple code , attached below,  referring to : https://devzone.nordicsemi.com/f/nordic-q-a/8707/how-to-use-timer1-capture-function

int main(void)
{    
  Init_HFCLK();			// HF clock launching	
	Init_RTC();				// RTC Timer interrupt setting // DAFARE inserire timer per IR led
	Init_IO();				// I/O pinout setting
	Init_PPI();
			
	while(1)
	{
		__NOP();
	}
}

void Init_PPI(void)
{
    NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
//		NRF_PPI->CH[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_COUNT;
		NRF_PPI->CH[1].TEP = (uint32_t)&NRF_TIMER1->TASKS_CAPTURE[3];

    NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos);
}

// RTC Timer interrupt setting
void Init_RTC(void)
{
  NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;  // set Timer mode

  NRF_TIMER1->TASKS_CLEAR = 1;               // clear the task first to be usable for later

	NRF_TIMER1->PRESCALER = 4;
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_24Bit; //Set counter 24 bit resolution
	
	NRF_TIMER1->CC[1] = 1000;
  NRF_TIMER1->CC[2] = 250; 
	
	NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE2_Enabled << TIMER_INTENSET_COMPARE2_Pos) | (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos);
		
	NVIC_EnableIRQ(TIMER1_IRQn);    
  NRF_TIMER1->TASKS_START = 1;   // Start TIMER
}


void Init_IO(void)
{
	// OUTPUT  	
	nrf_gpio_cfg_output(LED_FB);
	nrf_gpio_pin_clear(LED_FB);	

	// INPUT		
	nrf_gpio_cfg_input(IN_pin,NRF_GPIO_PIN_NOPULL);
	nrf_gpiote_event_config(0, IN_pin, NRF_GPIOTE_POLARITY_TOGGLE); //GPIOTE gives an interrupt on pin change
}

void Init_HFCLK(void)
{
//	NRF_CLOCK->XTALFREQ = 0x0;
	  NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
}
void TIMER1_IRQHandler (void)
{
	if ((NRF_TIMER1->EVENTS_COMPARE[2] != 0) && ((NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE2_Msk) != 0))
  {
		NRF_TIMER1->EVENTS_COMPARE[2] = 0;
		
		NRF_TIMER1->CC[2] += 250;//TMR_BASE;	// retrigger compare interrupt
		
		nrf_gpio_pin_set(LED_FB);
  }
	
	if ((NRF_TIMER1->EVENTS_COMPARE[1] != 0) && ((NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE1_Msk) != 0))
  {
		NRF_TIMER1->EVENTS_COMPARE[1] = 0;
		
		NRF_TIMER1->CC[1] += 1000;
		
		nrf_gpio_pin_clear(LED_FB);
				
//		NRF_TIMER1->TASKS_START = 1;
	}	
	
}

This is the first time I'm using the PPI and I'm a bit confused about its working. 

It seems Timer1 interrupt works as expected, as far as LED_FB (output pin) toggles, but I supposed that, when the input signal changes its level value, from L to H or H to L, an interrupt on Timer 1 is triggered and capture timer is saved in CC[3]. This, actually, doesn't happen. 

How do I have to modify the code to save capture timer in CC[3], or in some other register?

Thanks in advance for your support. 

Kind regards

Cristian

  • Hi,

    I have not studied your code in details, but it seems that the PPI stuff is up an running, so the value of the timer should be stored in CC[3]. However, you will not get an interrupt from the timer task endpoint, so you must generate the interrupt from GPIOTE. There is nothing doing that in the code you have included. Assuming you use SDK 12.3 and continue to use the driver for GPIOTE, you enable interrupts with nrf_drv_gpiote_in_init(). The interrupt will be handled by the driver, which will call the event handler that you registered with nrf_drv_gpiote_in_init().

Related