Setting up a TC for SAMD51 to count milli-seconds


After reading datasheet of SAMD51 for TC I have currently setup a TC(Timer/Counter) for the SAMD51 so it overflows every 0.001092 seconds,and then it increments a variable using the INTFLAG.OVF status.And when the variable reaches 999, it resets to 0(see below).It seems to work,but it lags abit, but I was wondering if theres a better way?

The reason is bc I would like to include a millisecond timestamp in the form of (0-999mS) for when I create a filename in code. And the reason for 0-999mS is just to make sure I dont re-open the last file and write data to it.

I currently have the ADC setup for 2 channels,INTERLEAVED,50kHz each(see link below).
-If a threshold is passed
-get current timestamp
-use timestamp as filename (ex:year-month-day-hour-minute-seconds.bin)
-record X samples,
-write to SD.
-close file
Pretty basic......

But the issue is filename! My filename uses timestamp up to seconds. This is no good. if a threshold is passed BEFORE a second has passed after it writes to SD and closes file,it'll write new data to same file if a second has not passed.

It only takes 20mS to write my data to SD card....So after it writes to SD card and closes file,it then starts looking for next threshold pass.

And I do know about millis() function but....weres the fun in that.I was wondering if theres a better way of going about this then the way I did. My millisecond counter lags a lil bit.

But I was just wondering what the best solution would be using a TC?

TC Code:

int roll = 0;
int sec = 0;
void setup()

  Serial.begin(115200);           // Open the native USB port at 115200 baud
  while (!Serial);                // Wait for the console to be opened
  GCLK->PCHCTRL[TC0_GCLK_ID].reg = GCLK_PCHCTRL_CHEN |         // Enable perhipheral channel for TC0
                                   GCLK_PCHCTRL_GEN_GCLK0;     // Connect generic clock 0 at 120MHz

  TC0->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16;              // Set-up TC0/TC1 timers in 16-bit mode
  TC0->COUNT16.CTRLA.bit.PRESCALER =  TC_CTRLA_PRESCALER_DIV2_Val; //120mhz/2=60mhz.....65536/60mhz=0.0010923 seconds per overflow
  TC0->COUNT16.INTENSET.bit.OVF =  0X01; //enable interrupt on overflow
  TC0->COUNT16.CTRLA.bit.ENABLE = 1;                 // Enable timer TC0
  while (TC0->COUNT16.SYNCBUSY.bit.ENABLE);          // Wait for synchronization

void loop()

  if (TC0->COUNT16.INTFLAG.bit.OVF == 1) {                  //if overflow happens,increment roll


    TC0->COUNT16.INTFLAG.bit.OVF =  0X01; //re-enable interrupt on overflow
    if (roll >= 999) {
      roll = 0;
      Serial.println("roll = ");
      Serial.println("sec = ");


And heres how I setup my ADC 2 Channels, @ 50kHz each(thanks to MartinL):

Is there something wrong with "millis() % 1000" ?

Nope lol,just wanted to play with a TC..

Hi geryuu123,

It’s possible to use the RTC in conjuction with the event system and a TC timer to generate a real-time millisecond accurate timestamp.

I’ve posted an example here:, in posts #4 and #5. It has been written for the SAMD21, but could modified for the SAMD51 with a few register tweaks.

This is awesome,ty!!