-
-
Save jdneo/43be30d85080b175cb5aed3500d3f989 to your computer and use it in GitHub Desktop.
#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; | |
} | |
} |
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!
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.
Awesome! Thanks for putting this up.
TcCount16* TC = (TcCount16*) TC3;
TcCount16* is not declared any where
error mesage comming please explain
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.
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!