This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Setting TIMER2 interval

How do I set TIMER2 to interrupt every 1 ms?

Sounds like a very basic question, but I haven't succeed. For TIMER1 I can get it working, but for TIMER2 the highest frequecy I have achieved is about 100 Hz.

The code is as follows:

void init_timer2(void)
{
	// Start 32 MHz crystal oscillator
	NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
	NRF_CLOCK->TASKS_HFCLKSTART = 1;
	// Wait for the external oscillator to start up
	while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {
		// Do nothing.
	}
	NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
	NRF_TIMER2->PRESCALER = 4; // what should be here?
	NVIC_EnableIRQ(TIMER2_IRQn);
        NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
        NRF_TIMER2->CC[0] = ???;
        NRF_TIMER2->CC[1] = ???;
        NRF_TIMER2->CC[2] = ???;
        NRF_TIMER2->CC[3] = ???; 
	NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE2_Enabled
	<< TIMER_INTENSET_COMPARE2_Pos;
	sd_softdevice_forward_to_application();
	NRF_TIMER2->TASKS_START = 1;
}

I don't know what should be put into the place of '???'s above. I guess there is a good documentation somewhere, so I would be happy to get a pointer there, too. Indeed, a working code would be best.

Edit: Format (please use preformatted text button when inserting code)

  • Hi,

    The prescaler sets the base timer tick like this (given in us): TimerTick = 16M / 2^prescaler.

    For instance, if we set 4: TimerTick = 16M/2^4 = 1 us.

    In order to generate an interrupt each 1ms:

    
    #define TIMER2_CC_DELAY 1000
    ...
    NRF_TIMER2->PRESCALER = 4;
    NRF_TIMER2->CC[0] = TIMER2_CC_DELAY; // Fbase = 16M/2^4 * 1000 = 1 ms.
    /*Reset of init*/
    
    

    In your handler:

    
    void TIMER2_IRQHandler(void)
    {    
        if(NRF_TIMER2->EVENTS_COMPARE[0])
        {
            nrf_gpio_pin_toggle(18);
            NRF_TIMER2->EVENTS_COMPARE[0] = 0;
            // Need to update the CC[0]
            NRF_TIMER2->CC[0] += TIMER2_CC_DELAY;
        }
    }
    

    For a more precise measurement you can add a static variable inside the interrupt handler to count instead of reading the CC[]-register.

    Best regards Håkon

  • For some reason, I had to use CC[2] instead of CC[0] to get it working. Could it has something to do with S110 soft device which I am using at the same time? Anyway, thanks!

  • Hi Jarmo,

    It's most likely because you enabled CC[2]: NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE2_Enabled Enabling CC[0] is done like this: NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Enabled

    BR Håkon

  • Hello Håkon, Thanks for this. I was able to start working with the timer by referring this code. But I have a question that whether the line, NRF_TIMER2->CC[0] += TIMER2_CC_DELAY; can be removed here ? But when I tried that , the toggling was not proper. why is this so?

    thanks, Mo

  • The reason this must be there is because the timer is not cleared between each interrupt. When you've finished your first interrupt, the timer will keep on incrementing until it overflows. You then have two options:

    1. Keep updating the CC-register
    2. Clear the timer between each interrupt. This can be done manually, or via SHORTS register.

    Best regards Håkon

Related