ok so i have gone over the data sheets a ton and i just can't figure out how to setup a
one shot timer
i have an external interrupt running some code and turning a few pins on (no digital write, setting ports directly)
but have a set time (50ms) i need to turn the pins off but i have serial + i2c data going on so need to get in and out and mills is just nowhere near reliable I need 50ms pulse 100% of the time but still need to change it at times.
pseudo code
ext_irq()
{
set_pin_high:
set countdown value
start countdown irq
}
countdown_irq() { clr pins }
anyone know a quick way to do this
Hi techmasterjoe24,
Probably the easiest way to do this is to use the oneshot function on the TCC0 timer.
The following code sets up a RISING edge interrupt on digital pin D12, using the attachInterrupt() function. The TCC0 timer is then configured for oneshot operation and to output a 50ms pulse on digital pin D7, each time the oneshot is triggered.
When the interrupt function is called, it simply triggers the oneshot, causing the TCC0 timer to output a 50ms pulse:
// Output a 50ms pulse on D7 when a RISING interrupt is received on D12
void setup()
{
attachInterrupt(12, interrupt, RISING); // Set-up an interrupt on digital pin D12
GCLK->GENDIV.reg = 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
GCLK->GENCTRL.reg = 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
// Enable the port multiplexer for the TCC0 PWM channel 3 (digital pin D7), SAMD21 pin PA21
PORT->Group[g_APinDescription[7].ulPort].PINCFG[g_APinDescription[7].ulPin].bit.PMUXEN = 1;
// Connect the TCC0 timer to the port outputs - port pins are paired odd PMUO and even PMUXE
// F & E specify the timers: TCC0, TCC1 and TCC2
PORT->Group[g_APinDescription[7].ulPort].PMUX[g_APinDescription[7].ulPin >> 1].reg |= /*PORT_PMUX_PMUXO_F |*/ PORT_PMUX_PMUXO_F;
// Feed GCLK4 to TCC0 and TCC1
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
// Normal (single slope) PWM operation: timer countinuouslys count up to PER register value and then is reset to 0
TCC0->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; // Setup single slope PWM on TCC0
while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization
// Each timer counts up to a maximum or TOP value set by the PER register,
// this determines the frequency of the PWM operation:
TCC0->PER.reg = 2399999; // Set the frequency of the PWM on TCC0 to 20Hz or 50ms
while (TCC0->SYNCBUSY.bit.PER);
// The CCBx register value corresponds a 50ms pulsewidth
TCC0->CC[3].reg = 2399999; // TCC0 CCB3 - 100% duty cycle on D7
while (TCC0->SYNCBUSY.bit.CC3);
TCC0->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT; // Enable oneshot
while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization
// Set oneshot operation to output 0V when the timer is stopped on PA21, channel W0[7] = TCC0 channel 3 output
TCC0->DRVCTRL.reg |= TCC_DRVCTRL_NRE7;
// Divide the 48MHz signal by 1 giving 48MHz (20.8ns) TCC0 timer tick and enable the outputs
TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1; // Divide GCLK4 by 1
// Divide the 48MHz signal by 1 giving 48MHz (20.8ns) TCC0 timer tick and enable the outputs
TCC0->CTRLA.bit.ENABLE = 1; // Enable the TCC0 output
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void loop() {}
void interrupt()
{
if (TCC0->STATUS.bit.STOP) // Check if the previous pulse is complete
{
TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER; // Retrigger the timer's One/Multi-Shot pulse
while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization
}
}
it works as written and thank you
based on your code I'm going to see if it can be tweaked to run on TC4(1) aka PB09 on d21J as this is a custom board kinda my take on an Industrial Arduino
I can use it as is just learn more from messing with it