Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Timer Interrupt example for Adafruit Feather M0. Callback function can be written in TC3_Handler().
#define LED_PIN 13
#define CPU_HZ 48000000
#define TIMER_PRESCALER_DIV 1024
void startTimer(int frequencyHz);
void setTimerFrequency(int frequencyHz);
void TC3_Handler();
bool isLEDOn = false;
void setup() {
pinMode(LED_PIN, OUTPUT);
startTimer(10);
}
void loop() {}
void setTimerFrequency(int frequencyHz) {
int compareValue = (CPU_HZ / (TIMER_PRESCALER_DIV * frequencyHz)) - 1;
TcCount16* TC = (TcCount16*) TC3;
// Make sure the count is in a proportional position to where it was
// to prevent any jitter or disconnect when changing the compare value.
TC->COUNT.reg = map(TC->COUNT.reg, 0, TC->CC[0].reg, 0, compareValue);
TC->CC[0].reg = compareValue;
Serial.println(TC->COUNT.reg);
Serial.println(TC->CC[0].reg);
while (TC->STATUS.bit.SYNCBUSY == 1);
}
void startTimer(int frequencyHz) {
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3) ;
while ( GCLK->STATUS.bit.SYNCBUSY == 1 ); // wait for sync
TcCount16* TC = (TcCount16*) TC3;
TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
// Use the 16-bit timer
TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
// Use match mode so that the timer counter resets when the count matches the compare register
TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
// Set prescaler to 1024
TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024;
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
setTimerFrequency(frequencyHz);
// Enable the compare interrupt
TC->INTENSET.reg = 0;
TC->INTENSET.bit.MC0 = 1;
NVIC_EnableIRQ(TC3_IRQn);
TC->CTRLA.reg |= TC_CTRLA_ENABLE;
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
}
void TC3_Handler() {
TcCount16* TC = (TcCount16*) TC3;
// If this interrupt is due to the compare register matching the timer count
// we toggle the LED.
if (TC->INTFLAG.bit.MC0 == 1) {
TC->INTFLAG.bit.MC0 = 1;
// Write callback here!!!
digitalWrite(LED_PIN, isLEDOn);
isLEDOn = !isLEDOn;
}
}
@servodave
Copy link

servodave commented Jul 8, 2017

Excellent! I am an old hand at AVR (pre-arduino...) but new to ARM arch. You saved me about two hours dredging through the Cortex M0 datasheet working out how to set this up. THX!

@mjbella
Copy link

mjbella commented Jan 8, 2018

This is exactly what I was looking for. This is a fantastic starting point for me to get up to speed on this new part!

Thank you!

@WyseNynja
Copy link

WyseNynja commented May 30, 2018

I'm using a library that has already defined TC3_Handler. Is there another timer I can use on the Adafruit Feather M0? It looks like there is a T4 and T5, but a simple find+replace of T3 didn't work.

Also, where are docs for this?

EDIT: I found another gist that sets up T5: https://gist.github.com/nonsintetic/ad13e70f164801325f5f552f84306d6f. Still curious where docs explaining this are.

@jrleeman
Copy link

jrleeman commented Apr 21, 2019

Awesome! Thanks for putting this up.

@ANUPAM1976
Copy link

ANUPAM1976 commented Nov 3, 2019

TcCount16* TC = (TcCount16*) TC3;
TcCount16* is not declared any where
error mesage comming please explain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment