Go Down

Topic: TImer in CTC mode (Read 463 times) previous topic - next topic

Manuel_Silva

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:

Code: [Select]


#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

MartinL

#1
Feb 21, 2019, 11:22 pm Last Edit: Feb 21, 2019, 11:23 pm by MartinL
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

Manuel_Silva

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

MartinL

#3
Feb 22, 2019, 01:27 pm Last Edit: Feb 22, 2019, 08:56 pm by MartinL
Hi Manuel,

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

Code: [Select]
// 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

Manuel_Silva

Hi Martin,

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

Best regards,
Manuel

Manuel_Silva

Hi Martin,

Its OK,
Thanks again.
Best regards,
Manuel

Go Up