Skip to main content

 I urgently need individuals who are willing to cooperate on my website and projects.

SAMD21 Timer library for the SAM15x15 and Arduino Zero

Published: 22 January 2017
Last updated: 15 July 2021

Intro

For the SAM15x15 Arduino compatible board, which uses the SAMD21G, I needed a timer library. Unfortunately, such a library didn't exist, so I have time invested in its development myself.
This library is usable for the Arduino Zero and equivalent boards too:

SAM15x15 Arduino compatible boardSAM15x15 Arduino compatible boardAdafruit Feather M0Adafruit Feather M0

Without having a sophisticated library, using the Timer/Counter is a complicated task and you have to go into many details such as counter modes, compare/capture channels, prescaler values etc. Here, a proper library makes life easier. I'm lazy, the only thing I want to do is specify the period time and the output pin, and the rest should be figured out by the library.

Download

Download the avdweb_SAMDtimer library from GitHub, you will find here program examples too.
The Adafruit_ZeroTimer library and the Adafruit_ASFcore should also be installed. 
Attention: The new libraries Adafruit_ASFcore and Adafruit_ZeroTimer don't work anymore with the avdweb_SAMDtimer library. Therefore, install these 2 old libraries:
http://www.avdweb.nl/images/Arduino/SAMDtimer/Adafruit_ASFcore-master.zip
http://www.avdweb.nl/images/Arduino/SAMDtimer/Adafruit_ZeroTimer-master.zip

Adafruit_ASFcore-master library bug (this is solved in the zip files above)

The Adafruit_ASFcore-master library has a bug which may generate a compiler error:
Expected '}' at end of input.
When this happens, you have to edit the system_interrupt.h file in the map:

Arduino-Sketchbook\libraries\Adafruit_ASFcore-master
Change this line at the bottom will fix it:
//}       // remove due to nested extern C' complaints
to
}       // remove due to nested extern C' complaints

1 Using a timer with an output pin

The library is easy to use; the following code generates a square wave of 1Hz to pin 5 of the Arduino Zero:

SAMDtimer mytimer1 = SAMDtimer(3, TC_COUNTER_SIZE_16BIT, 5, 1e6);

Explanation:

  • Mytimer1: this is the object name of you choice.
  • 3: the pin-table shows that timer3 should be used for output pin 5.
  • TC_COUNTER_SIZE_16BIT: don't change. This parameter exists just to make the library expandable.
  • 5: output pin 5
  • 1e6: we need to specify the period time in microseconds.

Alert readers might notice that the first two parameters are not strictly necessary because these could be derived from the used pin and period time. However, this would make the timer library less expandable and there will be occur more mistakes with the pin assignments, if more timers are used.

Notes

  • The maximum period time is 1398080us (0.7Hz).
  • The minimum period time is = 2us (500kHz).
  • For now, the library has three timers available (number 3, 4, 5), only in 16-bit mode.
  • There is no check on the proper parameters values.
  • Without specifying the pulse width, it is the half of the period time (duty cycle 50%).

2 Timer interrupts

A timer can also be used for calling interrupts, without using a timer output pin. To periodically execute an ISR, simply use this code:

SAMDtimer mytimer2 = SAMDtimer(4, myISR, 5e5);

Explanation:

  • Mytimer2: this is the object name of you choice.
  • 4: take any free timer
  • myISR: the name of the ISR of you choice.
  • 5e5: the period time in microseconds.

The ISR should look as follows, don't try to understand, just do it:

void myISR (struct tc_module *const module_inst)
{ your code here
}

3 Attaching interrupts to a timer with an output pin

A timer can be used for both calling an interrupt and steering its output pin at the same time. This has to be carried out in two steps: first create a timer with an output pin, and than attach an ISR to it.

Mytimer3.attachInterrupt(myISR);

Explanation:

  • Mytimer3: an existing timer with an output pin, see paragraph 1.
  • myISR: the name of the ISR, see paragraph 2.

Notes

  • If the timer is disabled, then the ISR is disabled also.

Wanted

SAMD21 Timer/Counter pins

Each timer has its own available pins and this distribution is rather messy as you can see here:

SAM15x15 and Arduino Zero Timer/Counter pinsSAM15x15 and Arduino Zero Timer/Counter pins

Future improvements

The timers 0, 1, 2 and the 8-bit modes are not implemented yet. I hope that other people want to do this on GitHub.
More functions can be added also, such as:
setPeriod_us(us);

Higher frequencies

The timer can produce frequencies above 500kHz, but since the period time is specified in microseconds, the maximum frequency is 500kHz. For higher frequencies, the fast PWM-DAC library can be used, but I prefer to have a function that allows to set higher frequencies. So this may be the next extension...

Arduino SAMD board under test on my workbenchArduino SAMD board under test on my workbench