Skip to content

Instantly share code, notes, and snippets.

@nanase
Last active August 6, 2019 06:02
Show Gist options
  • Save nanase/bdbf066f738e399c8601468fd4cc2fb3 to your computer and use it in GitHub Desktop.
Save nanase/bdbf066f738e399c8601468fd4cc2fb3 to your computer and use it in GitHub Desktop.

Formula

f = F / N (CC0 + 1)
CC0 = F / f * N - 1

where:

f = timer frequency (Hz)
F = global frequency (Hz)
N = timer prescaler
CC0 = value in the CC0 register

List of CC0 and f

when: F = 48 MHz use 16 bit counter

N CC0 f 1/f
1024 65535 0.715 Hz 1.398 s
1024 46874 1 Hz 1 s
256 18749 10 Hz 100 ms
256 1874 100 Hz 10 ms
64 749 1 kHz 1 ms
64 74 10 kHz 100 us
16 29 100 kHz 10 us
16 2 1 MHz 1 us
8 2 2 MHz 500 ns
8 1 3 MHz 333 ns
4 2 4 MHz 250 ns
4 1 6 MHz 167 ns
2 2 8 MHz 125 ns
2 1 12 MHz 83 ns
1 2 16 MHz 63 ns
1 1 24 MHz 42 ns
volatile bool led_state = false;
// ref: https://forum.arduino.cc/index.php?topic=425385.msg2931200#msg2931200
// Set timer TC4 to call the TC4_Handler every second
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
// Set up the generic clock (GCLK4) used to clock timers
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK4
GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Feed GCLK4 to TC4 and TC5
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_TC4_COUNT16_CC0 = 0xB71A; // Set the TC4 CC0 register as the TOP value in match frequency mode
while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
//NVIC_DisableIRQ(TC4_IRQn);
//NVIC_ClearPendingIRQ(TC4_IRQn);
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)
REG_TC4_INTFLAG |= TC_INTFLAG_OVF; // Clear the interrupt flags
REG_TC4_INTENSET = TC_INTENSET_OVF; // Enable TC4 interrupts
// REG_TC4_INTENCLR = TC_INTENCLR_OVF; // Disable TC4 interrupts
REG_TC4_CTRLA |= 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_ENABLE; // 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:
digitalWrite(LED_BUILTIN, led_state ? HIGH : LOW);
led_state = !led_state;
REG_TC4_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag
}
}
#include "Adafruit_ZeroTimer.h"
Adafruit_ZeroTimer zt4 = Adafruit_ZeroTimer(4);
void TC4_Handler() {
Adafruit_ZeroTimer::timerHandler(4);
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
zt4.configure(TC_CLOCK_PRESCALER_DIV1024, // prescaler
TC_COUNTER_SIZE_16BIT, // bit width of timer/counter
TC_WAVE_GENERATION_MATCH_FREQ // match style
);
zt4.setCompare(0, 0xB71A); // 1 match, channel 0
zt4.setCallback(true, TC_CALLBACK_CC_CHANNEL0, Timer4Callback0); // set DAC in the callback
zt4.enable(true);
}
void loop() {}
void Timer4Callback0() {
digitalWrite(LED_BUILTIN, led_state ? HIGH : LOW);
led_state = !led_state;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment