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
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?
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.
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
}
}