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

Timer is not accurate with softDevice.

Hi nordics!

First of all, thanks for answering my questions before.


Now, I want to generate a clock(48 pulses) with 200us width.

However, sometimes the width of pulse(clock) is not accurate.

image description

**yellow line is the clock line.

(Maybe it is because of the softDevice... I should make the pulse during BLE connection)

I read some post that I need to make the timer interrupt with GPIOTE, but I don't know how to make the timer interrupt with GPIOTE.

Can you fix my code up, or let me know some examples?

This is my code.

Thanks.


void timer2_init(void) {

uint32_t err_code;

// Configure timer
NRF_TIMER2->MODE      = TIMER_MODE_MODE_Timer;
NRF_TIMER2->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
NRF_TIMER2->PRESCALER = 4;


// Clear the timer
NRF_TIMER2->TASKS_CLEAR = 1;
NRF_TIMER2->CC[0] = 100;

NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
NRF_TIMER2->SHORTS=(TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
//NRF_TIMER1->TASKS_START = 1;

err_code = sd_nvic_SetPriority(TIMER2_IRQn,3);
APP_ERROR_CHECK(err_code);  

}

void TIMER2_IRQHandler(void) {

if ((NRF_TIMER2->EVENTS_COMPARE[0] == 1) && 
    (NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk))
{
    NRF_TIMER2->EVENTS_COMPARE[0] = 0;
    
    if(tick==0){
        nrf_gpio_pin_set(SCL);
        tick=1;    
    }
    else if(tick==1){
        nrf_gpio_pin_clear(SCL);
        tick=0;
        my_cnt++;  
    }  
}

//finish     
if(my_cnt==48){
  
    my_cnt=0;
    sd_nvic_DisableIRQ(TIMER2_IRQn);
    NRF_TIMER2->TASKS_STOP=1;
   
    nrf_gpio_pin_clear(SCL);   

}

}

static void my_app_timer_timeout_handler(void * p_context) {

 sd_nvic_ClearPendingIRQ(TIMER2_IRQn);
 sd_nvic_EnableIRQ(TIMER2_IRQn);  
 NRF_TIMER2->TASKS_START=1;
 nrf_gpio_pin_clear(SCL);

}

int main(void) {

// Initialize.
...
...

my_app_timer_init();
gpiote_init();
...
...
ble_stack_init();
scheduler_init();
...
...

my_app_timer_start();   //my_app_timer call the timer2 interrupt in every 20ms. 
advertising_start();
...
...
timer2_init();

// Enter main loop.
for (;;)
{
    app_sched_execute();
    power_manage();
}

}

Parents
  • Firstly, I believe: NRF_TIMER2->CC[0] = 100; should be: NRF_TIMER2->CC[0] = 99; as the counter counts from zero. Aside from that, I think that when the soft device is running, the timer interrupts may be delayed substantially, as the BLE stuff has to take priority. It is fairly easy to use events and tasks to generate rock-steady clock pulses(as the hardware handles everything), the only tricky thing will be how to stop at 48 pulses when the interrupts can get delayed by as much as your trace suggests. I notice you have referred to SCL in the code, so I assume this is being used in some capacity relating to I2C? If so, are you ignoring the SDA signal? Perhaps some better explanation of what you are trying to achieve will result in more useful answers.

Reply
  • Firstly, I believe: NRF_TIMER2->CC[0] = 100; should be: NRF_TIMER2->CC[0] = 99; as the counter counts from zero. Aside from that, I think that when the soft device is running, the timer interrupts may be delayed substantially, as the BLE stuff has to take priority. It is fairly easy to use events and tasks to generate rock-steady clock pulses(as the hardware handles everything), the only tricky thing will be how to stop at 48 pulses when the interrupts can get delayed by as much as your trace suggests. I notice you have referred to SCL in the code, so I assume this is being used in some capacity relating to I2C? If so, are you ignoring the SDA signal? Perhaps some better explanation of what you are trying to achieve will result in more useful answers.

Children
Related