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

nrf51822 Timer calculation

Hello Everyone,

Maybe this is a very silly question. I am trying to implement timer in nrf51822 with S130, SDK11.

Code snippet:

void TIMER1_IRQHandler(void)

{
  
if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0))
{
    
NRF_TIMER2->EVENTS_COMPARE[0] = 0;           //Clear compare register 0 event 
 
// do the required stuff when interrupt is fired
}
}

void start_timer(void)
{
    NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
    
NRF_TIMER1->TASKS_CLEAR = 1;
    // set prescalar n
    // f = 16 MHz / 2^(n)
    
uint8_t prescaler = 0;
    
NRF_TIMER1->PRESCALER = prescaler;
    
NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;

    // 16 MHz clock generates timer tick every 1/(16000000) s = 62.5 nano s
    // With compare enabled, the interrupt is fired every: 62.5 * comp1 nano s
    // = 0.0625*comp1 micro seconds
    // multiply this by 2^(prescalar)

    uint16_t comp1 = 10000;
    // set compare
    NRF_TIMER1->CC[1] = comp1;
    countToUs = 0.0625 * comp1 * (1 << prescaler); // time in us, set conversion factor 
                                                   // (1<<prescalar) left shift 1 with prescalar
                                                   //example: (1<<0) = 1
                                                   //         (1<<1) = 2
                                                   //         (1<<2) = 4 and so on

    // enable compare 1
    NRF_TIMER1->INTENSET =
        (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos); // INTSET- interrupt set register

    // use the shorts register to clear compare 1
    NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE1_CLEAR_Enabled <<
                          TIMER_SHORTS_COMPARE1_CLEAR_Pos);  
    NVIC_EnableIRQ(TIMER1_IRQn); // enable IRQ_handler
    NRF_TIMER1->TASKS_START = 1;// start timer

}

According to calculation: For 8 seconds timer, I need to set prescalar to 8 and comp1 to 1000000.

"countToUs = 0.0625 * comp1 * (1 << prescaler); // time in us, set conversion factor" Is the calculation correct? or am I going wrong in somewhere?

Thank you.

  • Did you try it out? Prescalar of 8 should give a CC value of 500 000 for 8 seconds timer ( (16 MHz / (2^PRESCALAR)) * 8 s = 500 000).

  • Here I am trying to toggle the led state for every 8 sec. I see that even if I change the value of NRF_TIMER2->CC[0] to 1000000, there is no change. When I keep the prescalar at 4 it toggles fast. At prescalar 8, it toggles at ~2-3 seconds. Am I missing something?

    There was mistake in code which I mentioned previously

    void start_timer(void)
    {    
      NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;  // Set the timer in Counter Mode
      NRF_TIMER2->TASKS_CLEAR = 1;               // clear the task first to be usable for later
      NRF_TIMER2->PRESCALER = 8;                             //Set prescaler. Higher number gives slower timer. Prescaler = 0 gives 16MHz timer
      NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit;     //Set counter to 16 bit resolution
      NRF_TIMER2->CC[0] = 500000;                             //Set value for TIMER2 compare register 0
        
      // Enable interrupt on Timer 2, both for CC[0] and CC[1] compare match events
      NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos) | (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos);
      NVIC_EnableIRQ(TIMER2_IRQn);
        
      NRF_TIMER2->TASKS_START = 1;               // Start TIMER2
    }
        
    /** TIMTER2 peripheral interrupt handler. This interrupt handler is called whenever there it a TIMER2 interrupt
     */
    void TIMER2_IRQHandler(void)
    {
      if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0))
      {
        // toggle the led
        NRF_TIMER2->EVENTS_COMPARE[0] = 0;           //Clear compare register 0 event 
      }
    
    }
    
  • Hello Jørgen,

    The timer 1 cannot operate in 32bit mode. So I think such higher count of CC have no effect on the timer.

  • You are correct, I only considered the calculation, not which timer instance you were using. Have you considered using RTC for generating the periodic timer? RTC have 24-bit registers and runs at 32.768 kHz, which is more suited for such long periods like 8s.

  • Hello Jorgen, I haven't tried RTC yet. But I used another method in which I made timer of 1 milli second using TIMER1. And when interrupt is fired i.e., 1 milli sec are over, a "counter" variable is incremented. As the counter reaches 8000, 8 seconds are over.

Related