TImer in CTC mode

Hello all,

I need help in configure a timer in CTC mode to have an ISR every about 120ms. I was using the Atmega328 pro mini, but, I had to change the zero mini due to lake of memory and I didn't study Zero timers yet because I need to finish the project (a robot) for my grandson´s birthday till March 8th.

I am using a Adafruit library but I am only getting about 87ms with a prescaller value of 64 or 384ms with a prescaller of 256. I do not know how to change the compare value to adjust the time. The code I am using is the following:

#include <Arduino.h>
#include "Adafruit_ZeroTimer.h"

// timer tester
Adafruit_ZeroTimer zt3 = Adafruit_ZeroTimer(3);

//define the interrupt handlers
void TC3_Handler(){
  Adafruit_ZeroTimer::timerHandler(3);
}

// the timer 3 callbacks
void Timer3Callback0()
{
 // digitalWrite(12, LOW);
  digitalWrite(12, digitalRead(12) ^ 1);   
}




void setup() {
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  analogWriteResolution(10);
  analogWrite(A0, 128); // initialize the DAC

  Serial.begin(115200);
  Serial.println("Timer callback tester");

  /********************* Timer #3, 16 bit, two PWM outs, period = 65535 */
  zt3.configure(TC_CLOCK_PRESCALER_DIV256, // prescaler
                TC_COUNTER_SIZE_16BIT,   // bit width of timer/counter
                TC_WAVE_GENERATION_NORMAL_PWM // frequency or PWM mode
                );

  zt3.setCompare(0, 0xFFFF/16);
  zt3.setCallback(true, TC_CALLBACK_CC_CHANNEL0, Timer3Callback0);  // this one sets pin low
  zt3.enable(true);
 
}

void loop() {

}

Your help is appreciated.
thanks in advance
regards
Manuel

Hi Manuel,

Do you just require the timer to trigger an ISR (interrupt service routine) every 120ms, or do you also require PWM outputs on a number of channels as well?

Kind regards,
Martin

Hi Martin,
Thanks for your reply.
I only need an ISR every 120ms to execute some code, like reading a joystick and send it out using the HC12 transceiver.

I will appreciate your help. I am very familiar with AVR timers, interrupts, etc, but this is my first experience with an ARM microcontroller and I do not have time to study the SAM21, because I need to finish the project for my grandson's birthday.

Thanks in advance,

Best regards,

Manuel

Hi Manuel,

Here's some code that gets timer TC4 to call its interrupt service routine every 120ms (8.33Hz):

// Set timer TC4 to call the TC4_Handler every 120ms
void setup() {
  // Feed GCLK0 to TC4 and TC5
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |                 // Enable GCLK0 to TC4 and TC5
                      GCLK_CLKCTRL_GEN_GCLK0 |             // Select GCLK0
                      GCLK_CLKCTRL_ID_TC4_TC5;             // Feed the GCLK0 to TC4 and TC5
  while (GCLK->STATUS.bit.SYNCBUSY);                       // Wait for synchronization
 
  TC4->COUNT16.CC[0].reg = 5624;                           // Set the TC4 CC0 register as the TOP value in match frequency mode
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);    // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);         // Connect TC4 to Nested Vector Interrupt Controller (NVIC)

  TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;              // Clear the interrupt flags
  TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF;             // Enable TC4 interrupts
 
  TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC |     // Reset timer on the next prescaler clock
                            TC_CTRLA_PRESCALER_DIV1024 |   // Set prescaler to 1024, 48MHz/1024 = 46.875kHz
                            TC_CTRLA_WAVEGEN_MFRQ |        // Put the timer TC4 into match frequency (MFRQ) mode 
                            TC_CTRLA_MODE_COUNT16;         // Set the timer to 16-bit mode      
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  TC4->COUNT16.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT16.STATUS.bit.SYNCBUSY);                // Wait for synchronization
}

void loop() {}

void TC4_Handler()                                         // Interrupt Service Routine (ISR) for timer TC4
{     
  // Check for overflow (OVF) interrupt
  if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF)             
  {
    // Put your timer overflow (OVF) code here....     
   
    TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF;             // Clear the OVF interrupt flag
  }
}

Kind regards,
Martin

Hi Martin,

Thanks very much for your help. I will try it this evening and let you know.

Best regards,
Manuel

Hi Martin,

Its OK,
Thanks again.
Best regards,
Manuel