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

nrf51822 app timer

Hi

I am trying to broadcast manufacturer data (beacon example) while changing data from second to second. For that I am trying to use timer2 (as timer 0 is used by SD, right).

...


void start_timer(void)
{
NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter; // Set the timer in Counter Mode
NRF_TIMER2->TASKS_CLEAR = 1; // clear the task first to be usable for later
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; //Set counter to 16 bit resolution
NRF_TIMER2->CC[0] = 5000; //Set value for TIMER2 compare register 0
NRF_TIMER2->CC[1] = 5; //Set value for TIMER2 compare register 1

// 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
}

//IMTER2 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))
{
NRF_TIMER2->EVENTS_COMPARE[0] = 0; //Clear compare register 0 event
nrf_gpio_pin_set(ADVERTISING_LED_PIN_NO); //Set LED
}

if ((NRF_TIMER2->EVENTS_COMPARE[1] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE1_Msk) != 0))
{
NRF_TIMER2->EVENTS_COMPARE[1] = 0; //Clear compare register 1 event
nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO); //Clear LED
}
}


int main(void)
{
//Initialization Zone
leds_init();


start_timer();

ble_stack_init();
advertising_init();
// Start execution.
advertising_start();
// Enter main loop.
for (;;)
{
power_manage();

}
}

No compiling errors but

If I call start_timer(); the whole program hangs (LED does not light)

Please, how to use timer?

Env: old rev nrf51822, softdevice 110 version 7 (recent SD make the app not work :-(   and SDK 6)

Imo

  • Your subject line mentions "app_timer" and indeed that is how you should be doing this.  The app_timer module in the SDK is a really easy and reliable way to create general purpose timers.  It can keep you from making all manner of mistakes with the general timers.

    In your example you make the mistake of setting timer 2 as a counter, instead of timer. Counters count, timers time.

    Also, using timer 2 for this function is kind of overkill since it runs on HF_clk and not the RTC. HF_clk uses substantially more power than the RTC.

    Make your life easier and read up on the app_timer in the SDK.  There are a lot of examples on how to use it.

  • Thanks for your explanation. Very clear!

    PS: I called app timer on the subject due to "app layer" timer creation but it seems that there is an code class to address it with the same name. Thanks! I am going to read about it

  • Yeah, I know you didn't literally mean app_timer.  That was just my bad attempt at a pun.

    This is based on SDK11, but I think it is similar for all. Everything can be put in main.c if you wish.

    #include "app_timer.h"

    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);

    APP_TIMER_DEF(m_your_timer_id);
    err_code = app_timer_create(&m_your_timer_id, APP_TIMER_MODE_REPEATED, your_timer_handler);
    APP_ERROR_CHECK(err_code);
                    
    err_code = app_timer_start(m_your_timer_id, APP_TIMER_TICKS(3630000, APP_TIMER_PRESCALER), NULL);
    APP_ERROR_CHECK(err_code);

    static void your_timer_handler(void * p_context)
    {
       Your code goes here;
    }

    Most of the examples utilize the app_timer so you may not be able to change the prescaler.  But basically you can use the app_timer to make as many timers as you wish with different attributes and different handlers.  The prescaler sets the basic resolution of the timer or systick. Then you are always creating a timer based on how many ticks it requires. You can always change advertising data on the fly since you are just changing the info in the data structure it points to.

    Depending on the type of device you are creating (eg, beacon), you could also approach your solution using Radio Notification. With radio notification a system event generates an interrupt for getting ready to transmit and also for finished transmitting.  I find radio notification very handy since I know the state of the radio when I wish to modify something.

  • NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter; // Set the timer in Counter Mode

    You are setting up the timer in counter mode, you need timer mode:

    NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Timer Mode

Related