Skip to content

Instantly share code, notes, and snippets.

@jdneo
Created December 8, 2016 02:21
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jdneo/43be30d85080b175cb5aed3500d3f989 to your computer and use it in GitHub Desktop.
Save jdneo/43be30d85080b175cb5aed3500d3f989 to your computer and use it in GitHub Desktop.
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;
}
}
@BlinkyStitt
Copy link

BlinkyStitt 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

Awesome! Thanks for putting this up.

@ANUPAM1976
Copy link

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

@rolfmobile99
Copy link

Awesome code sample, Sheng. This worked for me on the first try on a Feather M0.
I then adapted it to a different timer rate (200Hz) and that worked too.

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