ESE101: Configuring MSP430 Timers
Last time I explained the basics of what a microcontroller timer is and gave an overview of how timers are configured.
This time I’ll walk you through how to configure an MSP430 timer. We’ll use it to blink a light! (By now you’ve probably realized that most embedded system demos involve blinking a light. I’m pretty sure the singularity will look a lot like a rave.)
When configuring a timer you have to tell it:
- How fast to count
- How to count (up, down, or something else!)
- Whether to interrupt or not
For our timer + blinking light example, we’ll configure the MSP430 timer to run at a particular speed, count up from 0x0000 to 0xFFFF, and then each time it overflows from 0xFFFF to 0x0000 we’ll get an interrupt. Our timer’s ISR will blink a light.
The MSP430F5529 that we’re using has four individual timers. We’ll use the first of the timers, called TA0, which is short for “Timer_A 0 (zero)”. The other three timers (TA1, TA2, and TB0) are very similar to TA0.
Let’s look at each the three timer configuration steps in turn.
1. How fast to count
The MSP430 User’s Guide chapter 17.1, “Timer_A Introduction,” shows how the timer’s 16-bit counter register is hooked up to the MSP430 clock signals.
I’m including TI’s drawing and full text description here to show you what it looks like: don’t worry about understanding it as-is; I’ll explain it all below.
That’s a busy drawing, and a lot of text, so let me try to explain how I understand the drawing and text by using a lot more drawing and text of my own.
Start in the middle of the drawing, with the “16-bit Timer TAxR” box:
The box I’ve circled is the actual 16-bit counting register. This register is the thing that gets incremented (or decremented) as the timer counts up (or down). The “15” and “0” that I’ve drawn arrows to shows that the timer is 16-bits wide: it starts at bit 0 and goes up to bit 15; that’s 16 bits in total.
The drawing is generic for all of the Timer_A timers, so they call the register TAxR. For our timer, TA0, the actual counter register name is TA0R.
Okay, so that’s the counter register. How fast does it count? I’ve circled the important part in this next drawing:
See that little triangle on the left side of the TAxR box? That little triangle means that whatever signal goes into the triangle controls how fast the counter ticks. That triangle is the timer register’s clock input. The drawing shows that the signal going into the triangle is called “Timer Clock”, which is a good name for the clock that controls the timer speed.
So now we know TA0R will count at whatever speed the input Timer Clock signal is running at. How fast does Timer Clock run?
Let’s trace the Timer Clock signal all the way back to the far left side of the diagram to answer that question:
The circled part shows four signals: TAxCLK, ACLK, SMCLK, and INCLK. These are four different clock signals inside the MSP430. You select which of the four to use as the timer input clock using the TASSEL bits inside the timer peripheral configuration registers. TASSEL stands for Timer A Source SELection (that’s just my guess, but I’m pretty sure it’s a good guess.)
The slash through the line next to the number “2” tell you that TASSEL is 2 bits wide:
And the four values inside the isosceles trapezoid under the text TASSEL show the TASSEL value to select each of the four input clocks:
That isosceles trapezoid shape is the symbol for a multiplexer. A multiplexer is a circuit that sets its output signal to be one of the input signals based on its select signals. For example, if we set the TASSEL select signal to be 01, the input ACLK signal is sent as the output of that multiplexer, like this:
For this post I’m just going to tell you that we’ll use the ACLK clock input, and that it’s running at 32768 Hz. (Explaining the different clocks available on the MSP430 is a post for another day.)
Since I said we’ll use ACLK, we’ll want to set the TASSEL select bits to be == 01, which passes the ACLK signal through the multiplexer. You can think of it like this:
So now we have selected a 32768 Hz clock signal, but it doesn’t connect directly to the TA0R register’s clock input. The 32768 Hz clock signal passes through two more circuits called dividers. They do exactly what their name suggests: they take their input signal and divide it down by some amount.
Look at the divider labeled “ID”:
This divider can divide its input signal by 1, 2, 4, or 8. For example, if we set the ID divider to divide by 4 (commonly written as “/4”), it would take the input clock of 32768 Hz, divide it by 4, and the output would be 32768/4 = 8192 Hz. The divide by 1 (or “/1”) setting simply passes through the input signal unchanged.
The IDEX divider works the same, except that it can divide by 1, 2, 3, 4, 5, 6, 7, or 8.
What’s the point of these two dividers? Why have any dividers at all? Why have two?
The microcontroller designer doesn’t know how fast (or slow!) you’ll want to run your timer, so they want to give you as much flexibility as possible.
If they gave you no dividers at all, then you’d be stuck with whatever speed the four input clocks happened to be running at. That’s better than no options, but it’s hardly flexible.
If they gave you one divider like ID, you could take an input signal of 32768 Hz and use it as either 32768 Hz, 16384 Hz (/2), 8192 Hz (/4), or 4096 Hz (/8). That’s some more flexibility.
By adding a second divider like IDEX, the microcontroller designer has multiplied the number of frequencies you can produce, giving you a lot more flexibility. You can now run your timer from 32768 Hz (using both ID and IDEX set to /1) all the way down to 512 Hz (using both ID and IDEX set to /8).
Now that I’ve gotten you all excited about dividers (you *are* excited, right?), I’m going to mellow things out a bit and say let’s just use both ID and IDEX as /1 for our example. We’ll play with other options later.
By setting ID and IDEX as /1, the timer clock input looks like this:
And now we’ve finally finished the first step of configuring a timer: we’ve told it how fast to count. Our TA0R register will count at 32768 Hz, meaning it will tick 32768 times a second.
Phew. That was a lot of words and work. Hopefully my explanation made more sense than the original wall of text. Trust me: it might look complicated, but after you configure a few timers it starts to get easier!
Let’s move on to the remaining two timer configuration steps, which are both easier than this one was!
2. How to count (up, down, or something else!)
This one is a lot easier than the first step.The MSP430 Timer A has four different counting modes we can select using the MC configuration bits:
We’ll use the continuous mode, MC==10, for our example.
3. Whether to interrupt or not
When using continuous mode, the user’s guide tells us we can get an interrupt each time the timer register overflows from 0xFFFF back to zero:
This means that if we enable the timer interrupt, our TA0CTL register’s TAIFG bit will be set each time the timer overflows and the interrupt fires.
We'll use the interrupt so that its ISR will blink the light on and off.
Putting it all together
Okay, so we’ve walked through the three steps to configuring a timer:
- We configured it to tick at 32768 Hz.
- We configured it to continuously count from 0 to 0xFFFF.
- We configured it to interrupt when the timer overflows from 0xFFFF to 0.
If we’ve got this all configured properly then our interrupt will happen every 2 seconds: we used a 32768 Hz clock which provides 32768 ticks per second. Our timer overflows and interrupts after 65536 ticks. 65536 ticks / 32768 ticks/second = 2 seconds. (Reminder: The timer interrupts after 65536 ticks, not 65535 ticks: 65535 is 0xFFFF but don’t forget that zero counts too).
Normally you would first decide how fast you want your timer to run, and then pick the input clock and dividers. I chose to do it backwards for this post: I selected the input clock and dividers first so I could explain how the timer works.
That was a lot to throw at you in one sitting. Timers are sort of complicated, but hopefully you have a basic grasp of how the MSP430’s timer is configured. We’ll write the code and blink a light next time.
This post is part of a series. Check out the complete Embedded Software Engineering 101 series here.