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

How to use multiple timers

I have a device that I need to control, that needs 2 different square wave signals of different frequencies (although they may be multiples of each other), one at around 4 MHz and one at 10 KHz. Additionally (while the other two are running in the background) I need to communicate to the device with SPI upon an interrupt on a separate pin. To make matters worse, I will also need the SoftDevice for communications via BLE.

I have read that the nRF51822 only comes with 3 timers (one of which is reserved for th SoftDevice). Is there still a way to use one timer for multiple tasks?

Parents
  • Thanks Martin for your answer. I will go the PPI/GPIOTE way then. Am I correct in assuming, that given the frequencies are multiples (of 2) of each other I will be able to use a single timer for both square waves?

    I am still not very comfortable with dealing with this syntax. I found this sample code:

    static void ppi_init(void) {
    /* Configure PPI channel 0 to toggle PWM_OUTPUT_PIN1 on every Timer 1 COMPARE[0] match. */
    NRF_PPI->CH[0].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[0];
    NRF_PPI->CH[0].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[0];
    
    /* Configure PPI channel 1 to toggle PWM_OUTPUT_PIN1 on every Timer 1 COMPARE[1] match. */
    NRF_PPI->CH[1].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[1];
    NRF_PPI->CH[1].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[0];
    }
    

    How can I set the compare event for TIMER1? Do I need to set the GPIOTE "out task" to "toggle" explicitly? Where do I determine the pin to be toggled? Are there any higher level libraries for what I am trying to achieve?

  • Thanks AmbystomaLabs, your comments have been incredibly helpful! I got it working with the following minimal code (not worrying about SoftDevice and the like at the moment).

    int main(){
        sd_clock_hfclk_request();
        NRF_TIMER1->SHORTS      = (1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos); 
        NRF_TIMER1->PRESCALER   = 0; 
        NRF_TIMER1->CC[0]       = 1;   
        NRF_TIMER1->TASKS_START = 1;
        NRF_PPI->CH[0].EEP  = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
        NRF_PPI->CH[0].TEP  = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
        NRF_PPI->CHEN       = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos);
      
        NRF_GPIOTE->CONFIG[0] =((GPIOTE_CONFIG_MODE_Task       << GPIOTE_CONFIG_MODE_Pos)
                                |(6                         << GPIOTE_CONFIG_PSEL_Pos)
                                |(GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
                                |(GPIOTE_CONFIG_OUTINIT_Low     << GPIOTE_CONFIG_OUTINIT_Pos));
    }
    
Reply
  • Thanks AmbystomaLabs, your comments have been incredibly helpful! I got it working with the following minimal code (not worrying about SoftDevice and the like at the moment).

    int main(){
        sd_clock_hfclk_request();
        NRF_TIMER1->SHORTS      = (1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos); 
        NRF_TIMER1->PRESCALER   = 0; 
        NRF_TIMER1->CC[0]       = 1;   
        NRF_TIMER1->TASKS_START = 1;
        NRF_PPI->CH[0].EEP  = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
        NRF_PPI->CH[0].TEP  = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
        NRF_PPI->CHEN       = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos);
      
        NRF_GPIOTE->CONFIG[0] =((GPIOTE_CONFIG_MODE_Task       << GPIOTE_CONFIG_MODE_Pos)
                                |(6                         << GPIOTE_CONFIG_PSEL_Pos)
                                |(GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
                                |(GPIOTE_CONFIG_OUTINIT_Low     << GPIOTE_CONFIG_OUTINIT_Pos));
    }
    
Children
No Data
Related