A Simple and Interactive Explanation of the Teensy's 16-bit timer (Timer1)

by Tavish Armstrong

This page is a work in progress and needs some editing and bug fixes. Check my main site if this URL disappears. One thing to note is that I haven't done anything with the Clock Select in the diagram (yet).


When taking SOEN 422: Embedded Systems at Concordia in the Fall of 2012, I was frustrated by the lack of good documentation on the Teensy's hardware timers. All we had to do was recreate the Arduino analogWrite() function in straight C code, but that's a tricky thing to do. The hardware timers are built to do many things and you need to thoroughly understand what they do (but not how they do it) in order to use them. Usually you need only find the right modes and how to enable them. The best way to do this is to read the manual for the chip. This will tell you in excruciating detail what each register does, what the various modes do, etc. It contains timing graphs that show precisely how the timer interacts with its registers. However, that's 10 really, really detailed pages that you might misunderstand anyways.

This is my attempt at a more beginner-friendly explanation of the Teensy's Timer 1 and what it does.

The explanation

In the Teensy++, there are three timers. The second of these, Timer 1, is a 16-bit timer. It can be used for periodic interrupts, which lets you run a piece of code every so often. It can also be used for pulse-width modulation (PWM), which is a way to simulate analogue signals using digital signals. You can use this to dim an LED.

Remember in the first lab, where you turned an LED on by setting the output of a pin to HIGH? HIGH is 5 volts. If you turn it to LOW, that's 0 volts. With digital, there's no in-between. What you can do, however, is simulate a value in between 0 and 5 by changing the value quickly enough so that it appears to be between 0 and 5. The average voltage becomes the apparent voltage.

As with most things on the Teensy, you configure the behaviour of this Timer by setting various bits in various registers. It's useful to know what these registers are, and what the C constants for them are:

The Timer Counter Something Timer is a register that is automatically increased or decreased. In other words, it is the current value of the timer. Depending on the mode, it may count up until it reaches the special value TOP and then roll over to 0; or it may count up until TOP and then back down to 0.
The Output Compare Register (Channel A) is the register whose value is compared to the current value of TCNT1. Depending on the wave generation mode and the compare output mode, this may be used as the threshold after which one of the physical output pins is set to HIGH. See COM and WGM.

The Timer Counter/Control Register has two parts: TCCR1A and TCCR1B. Depending on which bits are set on this register, Timer 1 will behave differently. You can set the compare output mode (COM), the wave generation mode (WGM), and select a clock (CS).

// Here's some sample code showing how to set various bits on the TCCR1 registers.
TCCR1A |= (1 << COM1A1) | (1 << COM1A0); // Set COM to 3
TCCR1A |= (1 << WGM11) | (0 << WGM10); // Set lower two bits of WGM to 2.
TCCR1B |= (1 << WGM13) | (1 << WGM12); // Set higher two bits of WGM to 8 + 4. Total WGM = 14.
TCCR1B |=  (0 << CS12) | (1 << CS11) | (0 << CS10); // CS = 2.
I mentioned compare output mode. You can use these two bits to determine for what portions of TCNT's cycle the OC1A pin is on. For example, when COM = 3, the OC1A pin is set to HIGH when TCNT1 is greater than OCR1A.
Wave Generation Mode. This lets you choose between Non-PWM, PWM, and Fast-PWM modes; what the value of TOP is; and more. This four bit number is made up of two bits in the TCCR1A register and two bits in the TCCR1B register.
This is the MAX value of TCNT1. This can be a value between 0 and 0xFFFF because Timer 1 is a 16-bit timer. An 8-bit timer would have a maximum value of TOP equal to 0xFF. Lower values of TOP mean a higher frequency.
The Clock Select lets you choose a "pre-scaler" for the timer. For example, CS = 2 means that the timer operates at the speed of the CPU; CS = 3 means that the timer operates at FCPU/4; etc. This is another way to vary the frequency of the pulse.

Below is a plot of TCNT1 values over time, as a function of the TCCR1 registers and the values of the OCR1A and ICR1 registers. It will only display visualizations for Fast PWM modes. You can toggle the values of various bits in the registers to see what they affect in the graph. The diagram will also generate code for you.

ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10

Clock Select
Wave Generation Mode