Timer interrupts on XIAO

Does the XIAO support timer interrupts? If so, does anyone have a sample sketch for Arduino that demonstrates? I’m familiar with interrupts on the Uno, but my code fails to compile for the XIAO. Thanks.

You can try the API. I hope it meets your needs.
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

Thank you, that is most helpful.

That doesn’t look like a timer interrupt to me it looks like an interrupt on a pin.

Yeah, you’re right, that is all about interrupt pins

You’ve probably found something by now, so I guess this is for the benefit of anyone else looking

#include <Arduino.h>
#include <TimerTC3.h>

#define Transmission_Timer TimerTc3 

/****************
 * Forward declarations of functions
 *************************************************************/
void TRANSMISSION_ISR();
void transmit();

/****************
 * Evaluated to determine whether or not we need to send a message
 *************************************************************/
volatile bool TransmitNextMessage = false;

void setup()
{
  Serial.begin(115200);
  // allow time for serial start and port monitoring tool connection
  uint32_t timestamp = millis();
  while(millis() - timestamp < 2000)
    ;

  /****************
   * Initialize the timer and register the ISR function
   *************************************************************/
  Transmission_Timer.initialize();    // The default interval is 1000000 microseconds
  Transmission_Timer.attachInterrupt(TRANSMISSION_ISR);
}

unsigned long packetnum = 1; // packet counter, we increment per xmission
void loop()
{
  /****************
   * Disable the IRQ so that we can safely access the shared resource
   *************************************************************/
  __disable_irq();
  
  bool run = TransmitNextMessage;
  if(run)
    TransmitNextMessage = !TransmitNextMessage;

  /****************
   * Don't forget to reenable the IRQ
   *************************************************************/
  __enable_irq();

  if(run)
    transmit();
}

/****************
 * The ISR must return as quickly as possible
 *************************************************************/
void TRANSMISSION_ISR() { TransmitNextMessage = true; }

/****************
 * This function is called each time the Timer period elapses
 * but it happens as part of the main loop()
 * 
 * Remember that you should NEVER write to Serial
 * from within an ISR
 *************************************************************/
void transmit()
{
  Serial.printf("Hello World # %lu", packetnum++);
}


One of my teammates was working with an arduino mega while writing this code. now i have to use the Seeeduino XIAO, therefore the time interrupts isn’t working and i get compilation error. any suggestion ? (without too much change in the code)

hi this is Timer intterupt basic code

#include <TimerTC3.h>

void setup() 
{
    TimerTc3.initialize(1000000);
    TimerTc3.attachInterrupt(timerIsr);
}
void loop()
{    } 
void timerIsr()
{  /in your code  }
4 Likes

A very good hint. Simple and clear.

I think TimerTC3 has a bug.
I tried TimerTc3.initialize 10922 → 10923 and 10923 → 10922 in order.
Then the timer slowed down.

ex.
08:25:40.101 → CountUp:10922
08:25:40.101 → CountUp:10922
08:25:40.135 → CountUp:10922
08:25:40.135 → CountUp:10922
08:25:40.821 → CountUp:10923 <= +686msec
08:25:41.543 → CountUp:10923 <= +722msec
08:25:42.234 → CountUp:10923 <= +691msec

08:41:01.160 → CountUp:10923
08:41:01.160 → CountUp:10923
08:41:01.194 → CountUp:10923
08:41:01.194 → CountUp:10923
08:41:02.605 → CountUp:10922 <= +1.411sec
08:41:04.010 → CountUp:10922 <= +1.405sec
08:41:05.386 → CountUp:10922 <= +1.376sec

Setting from 10922 or less to 10923 or more or from 10923 or more to 10922 or less is NG ?

#include <Arduino.h>
#include <TimerTC3.h>

uint32_t tc_time = 10920;
int  count = 0;

void setup()
{
  Serial.begin(115200);

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  TimerTc3.initialize(tc_time);
  TimerTc3.attachInterrupt(int_timer);
  Serial.println("Start");
}

void loop()
{
  delay(10);
}

void int_timer()
{
  Serial.print("CountUp:");
  Serial.println(tc_time);
  if(++count >= 10)
  {
    tc_time++;
    TimerTc3.stop();
    TimerTc3.initialize(tc_time);
    TimerTc3.attachInterrupt(int_timer);
    count = 0;
  }
}

Self-resolved!
I fixed TimerTC3.cpp.
Thanks.

void TimerTC3::setPeriod(long microseconds)
{
    TcCount16 *TC = (TcCount16 *)TC3;

    uint32_t cycles = (CPU_HZ / 1000000) * microseconds;
    uint32_t prescalerConfigBits;

    if (cycles < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1;
    else if ((cycles >>= 1) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV2;
    else if ((cycles >>= 1) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV4;
    else if ((cycles >>= 1) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV8;
    else if ((cycles >>= 1) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV16;
    else if ((cycles >>= 2) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV64;
    else if ((cycles >>= 2) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV256;
    else if ((cycles >>= 2) < RESOLUTION)
        prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1024;
    else
        cycles = RESOLUTION - 1, prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1024;
/*
    SerialUSB.print("cycles is ");
    SerialUSB.println(cycles);
    SerialUSB.print("prescalerConfigBits is ");
    SerialUSB.println(prescalerConfigBits);
*/
    // Set prescaler
    uint32_t CtrlA = TC->CTRLA.reg;
    uint32_t Enable = CtrlA & TC_CTRLA_ENABLE;

    TC->CTRLA.reg = CtrlA & ~TC_CTRLA_ENABLE;
    CtrlA &= ~TC_CTRLA_PRESCALER_Msk;
    CtrlA |= prescalerConfigBits;
    //TC->CTRLA.reg |= prescalerConfigBits;
    TC->CTRLA.reg = CtrlA;
    while (TC->STATUS.bit.SYNCBUSY == 1)
        ;

    TC->CC[0].reg = cycles;
    while (TC->STATUS.bit.SYNCBUSY == 1)
        ;

    TC->CTRLA.reg |= Enable;
    while (TC->STATUS.bit.SYNCBUSY == 1)
        ;

    //TC->PER.reg = cycles;
    //while (TC->STATUS.bit.SYNCBUSY == 1);
}
1 Like