Encoder Front Page
SRS Home | Front Page | Monthly Issue | Index
Google
Search WWW Search seattlerobotics.org

The 68HC12 Timer Module

By Kevin Ross

kevinro@nwlink.com


You have seen some information about the 68HC12 in the Encoder before ( An Overview of the 68HC12 and Programming the 68HC12). This article is going to describe the basics of how to use the Standard Timer Module of the 68HC812A4.

If you have programmed the 68HC11 before, then the 68HC12 Timer Module is going to look very familiar, with the addition of a couple really cool features. If you have never seen the 68HC11 timer module, then rest easy, I will go through the basics of the 68HC812A4 timer section assuming you have no prior knowledge. It would be very helpful, however, if you had the 68HC812A4TS document handy. You can grab it from the web. This article is intended to help you understand what is in that document.

Overview

The purpose of the timer module is to allow for time critical operations to be handled by the hardware, instead of trying to accomplish everything in software. For example, generating wave forms or measuring waveforms is fairly straight forward using the timer module.

The 68HC12 Standard Timer Module consists of a 16-bit programmable timer that is driven by a programmable prescalar mechanism. It also has eight 16-bit input capture/output compare channels, and even a pulse accumulator. Each of these features will be explained in more depth later in this article.

The Standard Timer Modules functions mostly involved doing things based on the current value of the programmable timer. When, for example, an 'output compare' occurs, the hardware will automatically change the state of an output pin. An output compare means that the current value of the timer matches a trigger value set by the software.

For another example, when an 'input capture' occurs, the current value of the timer is stored in a special register. The input capture triggers when the state of one of the input pins changes in a specified way. This allows you to capture the exact time of some external event.

Whether you are doing robotics, or just about any other type of control application with a Microcontroller, the Standard Timer Module is a very powerful tool that you should consider investing the time to get to know.

The rest of this article will describe the various parts of the Standard Timer Module, and will demonstrate some software for performing specific tasks.

Big Picture

No good article can resist a nice block diagram. This one is from the Motorola MC68HC812A4 Technical Summary document (MC68HC812A4TS/D). It shows the major components of the Standard Timer Module. Actually, it is supposed to represent the functions relating to each pin (marked PAD in the diagram). A complete diagram would consist of 8 pins, which would require one heck of a lot of drawing!

As you can see in the diagram, there are lots of inter-related parts to the Timer Module. Many of the parts are dual purpose depending on the mode the pin is operating in (Input Capture or Output Compare). The important features of this diagram is to show how each pin has a relationship to the counter TCNT.

The Control Registers

Before anything happens in the Standard Timer Module, the software on the CPU must enable the timer system using the appropriate registers. The Timer System Control Register is the key register to deal with. This register, located at register offset $0086, controls the basic behavior of the entire timer module, such as whether it is running or not. It also controls how the timer system operates in various modes such as Background Debug Mode, WAIT state, and also how the timer flags are cleared.

Keep this in mind: if you are debugging a program that uses the timer section, you may wish to consider stopping the timers while in Background Debug Mode. Its an option available to you. If debugging your program is being very timing dependent, you may be able to debug the problem. Might be useful, might not. Lets move on.

The Counter

At the heart of the module is the Timer Count Register (TCNT). The TCNT register is a 16-bit counter that is attached to the Module clock (MCLK), which is derived from the CPU clock. Located at register offset $0084-$0085, this 16-bit counter is initialized to zero. Once it starts counting, (by setting Timer ENable in the TSCR) it increments by 1 for each tick of the timer sections clock. To confuse things a little bit, there is a prescalar register that allows you to change the relationship between MCLK and the TCNT register.

TCNT is a free running clock, and will keep right on incrementing regardless of the software state of the CPU. The next clock after TCNT reaches $FFFF will wrap it over to $0000. The only states that stop the clock are Wait and Background Debug Mode. The affects of both are controllable in the TSCR.

The prescalar is a useful tool. The prescalar allows you to control the amount of time it takes for a single increment of the clock. By default, the prescalar is set to 1 on reset, which means the TCNT register is incrementing at the MCLK speed. Normally, MCLK = Crystal Frequency / 2 : MCLK on a 16-MHz crystal is 8mhz. (It is possible to change the speed of MCLK by dorking with the CLKCTL register, but most people don't do that). Using the PR0-PR2 bits of the TMSK2 register, you can divide MCLK by up to 32. Here is a little chart to show the period of a 'tick' for an 8mhz MCLK. The TCNT duration shows the amount of time it takes for TCNT to overflow (i.e. count from $0000 to $FFFF + 1)

Prescalar value selection table

PR2 PR1 PR0 Period (8mhz MCLK) TCNT overflow Prescale Factor
0 0 0 125ns 8.192 ms 1
0 0 1 250ns 16.384 ms 2
0 1 0 500ns 32.768 ms 4
0 1 1 1us 65.536 ms 8
1 0 0 2us 131.072 ms 16
1 0 1 4us 262.144 ms 32

(ns = nano-second, us = micro-second, ms = millisecond)

(If you are an old hand at the 68HC11, you might notice that the 68HC12 is 4 times faster than the 'HC11. This is due to the MCLK frequency being the Crystal / 2, plus the maximum crystal speed being 16mhz on the 'HC12.)

Tic-Toc

As described previously, the Standard Timer Module has 8 channels. These channels can be individually programmed to be input capture or output compare. Your software must specify the function of each pin. This is done via the TIOS (Timer Input Capture/Output Compare Select) register, located at register offset $0080. Each bit of this register represents one of the channels. Setting a 1 in each bit makes that channel an output compare channel, while setting a 0 makes it an input capture. 68HC11 users will like this quite a bit, since you can select the function of each pin, instead of having it hardwired.

A common way to refer to a function is as a TIC (Timer Input Compare, pronounced as 'tick') or a TOC (Timer Output Compare, pronounced as 'tock').

Want to TOC?

When a channel is configured as TOC, it patiently sits and waits for the counter TCNT to equal a value that the software set into the channels Timer Input Capture/Output Compare Register (TCx). When the comparison occurs, a programmed event takes place, such as changing the state of a pin, or perhaps generating an interrupt.

Configuring a channel as a TOC involves setting values in several registers. Lets go through those now as an example. You will find a link to an SBASIC file that has source code that matches this example.

First, you will need to select the TOC function for the specific channel by setting a 1 in the TIOS register that corresponds to the channel number. Here, in SBASIC, is some code to setup channels 0 and 1 to be TOC channels

pokeb tios,%00000011 ' Channels 0 and 1 are TOC

What happens when a TOC triggers? Well, you can program each TOC channel with its own behavior. You can program the TOC to clear the output pin, set the output pin, toggle the output pin, or do nothing with the output pin. There are 4 cases, which require 2 bits of setup information for each channel. The control registers that determine the action are TCTL1 and TCTL2. TCTL1 handles channels 4-7, and TCTL2 handles channels 0-3. For this example, I will set channels 0 and 1 to toggle the bit each time a compare happens. Each channel is a group of 2 bits. Setting those two bits to '01' configures a toggle operation.

pokeb tctl2, %00000101 ' On output compare, toggle the bit

An important thing to determine is what prescale you would like to use. The prescale can be adjusted by putting a value in the prescalar. The prescalar divides the MCLK frequency to make the TCNT counter slower. As in the above table, PR2, PR1, and PR0 are the values that are used to set the prescaler. For this example, I am going to set the prescalar to slow the clock down as far as possible. It will provide us with a 4ms period for each increment of TCNT. Since there are 65535 possible values for TCNT, it takes 262.4 milliseconds for the counter to overflow. If you hook an LED and a current limiting resistor to these output pins, you should see the LED flash on and off about twice per second.

pokeb tmsk2,%00110101 ' Set the prescalar to maximum. 262.4ms overflow

There are two channels being set in our example. Just for kicks, I will set one of the channels to 0, the other to $8000.

poke tc0,0 ' TOC0 matches at zero
poke tc1,$8000 ' TOC1 is at $8000

All of the registers are setup, the compare values are set. The next thing to do is to start TCNT. There is a control bit in TSCR that turns the counter on and off. Next instruction sets TEN to 1, and also sets a flag that stops the timer unit when the background debugger is active.

pokeb tscr, %10100000 'Enable timer

When this code executes, it will setup channel 1 and 2 to be TOC channels. The channels will be about 262.4ms out of phase because of the differences in timer values. Here is an oscilliscope screen that shows the outputs from this program running on a 68HC812A4 development board. You can see that the period is 524ms for one full cycle, which is a frequency of nearly 2hz. Since the pins are set to toggle, it requires two output compares for a complete cycle. You can see the measurement bars (the vertical bars, one solid, one dashed). The upper right corner shows the delta measurement between the bards of 262.4ms, which is what we expected.

A complete SBASIC program that implements this is found in timer1.bas

What's TICing?

Another key function is the ability to capture the TCNT value when an external event occurs. Applications of Timer Input Capture include sonar ranging, wave form analysis, detecting modulated signals, and a host of other uses.

The registers you need to dork with are nice and easy. The following lines are also found in timer1.bas

'
' Setup channels 0 and 1 to be TOC channels.
' Setup channels 2 and 3 to be TIC channels.
'
        pokeb   tios,%00000011
'
' We are interested in capturing any changes in channel 2, or any rising
' edge in channel 3
'
        pokeb   tctl4,%01110000

The TCTL3 and TCTL4 registers determine what edge characteristics will be detected. You can choose from nothing, rising edges, falling edges, or any change. Two bits are required to configure each channel.

When a Timer Input Capture is triggered, the current value of TCNT is latched into the channels TCx register, and a bit gets set in the TFLG1 register to indicate that a capture has occured. It can optionally generate an interrupt as well.

In this example, the code polls the bits for channels 2 and 3

        '
        ' This loop is going to sit and spin, testing to see when a TIC
        ' event happens. When the TIC triggers, it sets a bit in TFLG1
        ' to indicate that a value is ready. To clear the flag indicating
        ' the TIC has happened, we write a 1 to its position in TFLG1
        '
        TicFlags = peekb(tflg1)
        if TicFlags AND $04 <> 0
                printx "TIC2: ",peek(tc2)
                pokeb   tflg1,peekb(tflg1) OR $04
        endif
        if TicFlags AND $08 <> 0
                printx "TIC3: ",peek(tc3)
                pokeb   tflg1,peekb(tflg1) OR $08
        endif

The TIC functions are pretty straight forward to use.

Allow me to interrupt

When a TIC or a TOC triggers, you can optionally set an interrupt handler for each channel. This allows your code to avoid having to poll. I am planning a whole article about interrupts on the 68HC12, so I am going to hold off until then for an in depth discussion about this subject.

TOC7

One of the TOC channels, channel 7 to be specific, can be configured to play a major role in the timer module. It can help control the state of the other TOC pins on the system. This very powerful function is really fairly easy to understand. When TOC 7 triggers by TC7 comparing with TCNT, then the channels selected in the register OC7M are set to the values specified in the register OC7D. (68HC11 hackers may recognize this as the OC1 function).

To use this feature, as always, there are a few registers to setup. Lets walk through them by example. Assume that you wanted to use the timer subsystem to run servo motors on channels 0 and 1. Servo motors typically require a pulse of duration 1.5 milliseconds every 20 milliseconds or so. The period of the pulse isn't critical, but the width of a pulse is extremely important. The width is what determines the angular position of the servo. The Timer Module does a very good job at providing precise pulses. As you can see in the scope shot below, I have setup two pulse trains. Both have a 32.76 ms period. One has a 2.119 ms width, the other has a .960ms width (or 960us). When driving a servo motor, the first makes the motor turn quite a distance in the clockwise direction, the other turns in the counter-clockwise direction.

How to set this up in software? As always, we need to set some registers.

'
' Setup channels 0,1, and 7 to be TOC channels.
'
	pokeb	tios,%10000011

'
' Set channels 0 and 1 to clear their output pins when the compare happens
'
	pokeb	tctl2, %00001010

'
' Set the prescalar to roll over on 32ms periods
'
	pokeb	tmsk2,%00110010

Setting up TOC7 to affect the other pins is fairly simple. The basics are that when TOC7 triggers, the values found in OC7D are transferred to the pins designated in OC7M. For our example, the code below sets up TOC0 and TOC1 to be set to 1 when TOC7 triggers. Previously, we setup TOC0 and TOC1 to clear (set to 0) the pins when they trigger. This means that there will be two timer events affecting each of these pins. The first will be TOC7 setting the line to go high when TCNT is 0. A little while later, TOC0 and TOC1 will cause the pins to be cleared. Adjusting the values in TOC0 and TOC1 will set the width or duration of the pulse.

'
' Setup TOC7 to handle the start of the pulses by setting the value to 1
' when the TCNT is zero
'
	pokeb	oc7m,%00000011
	pokeb	oc7d,%00000011
	poke	tc7,0

' Preset the positions of the servos to center

	poke  tc0, CenterPosition
	poke  tc1, CenterPosition
'
' Turn on the timer, disable it during background debug mode
'
	pokeb	tscr, %10100000

If you would like to try this out on your 68HC12, you can click here for the source code to timers2.bas

There is another very noteworthy feature about TOC7. TOC7 can be configured to cause a reset of TCNT ('Timer Counter Reset' or TCR). This means it is possible to setup the timer system so that when TCNT compares with TOC7, then TCNT is reset to zero. The implication of this is that you can change the 'overflow' period manually to anything you want it to be. For example, if you really wanted to have a 20ms PWM signal, then you would

Doing this requires some care, however. By setting up the 'Timer Counter Reset' function, you are changing the maximum value of TCNT. This will affect the values in the other channels because TCNT will never go over the value set in TOC7. For example, if you had TOC4 set to $A500, and TOC7 had $9C40 with the TCRE enabled, then TOC4 would never occur, because TCNT cannot reach $A500.

Using TOC7 to change the overflow rate also might have considerations on other parts of your software that are doing timing based on TCNT. If, for example, another routine is trying to wait for 30ms based on TCNT, it may run into trouble.

TOC7 resetting TCNT is a useful feature, but requires some thought first.

Forcing the issue

Another interesting feature, which also exists on the HC11, is the Timer Compare Force Register. Sometimes, you need to manually cause an action to occur that is normally handled by the timer functions. You can cause that action to occur by writing a 1 to the appropriate bit of the CFORC register. This causes the compare function to be executed right away. The one thing that doesn't happen, however, is that the interrupt flags do not get set in TFLG1. This was an unfortunate design decision by Motorola because it makes the functioning of CFORC not quite complete.

Summary

The Standard Timer Module is a very useful feature of the 68HC12. The Timer Output Compare functions allow you to generate nice clean wave forms without much software overhead. The Timer Input Compare functions allow you to capture external events with very good precision. The module is flexible and pretty easy to understand.

I didn't cover a couple of subjects relating to the Standard Timer Module. I plan to do so in the next few issues. I will discuss the operation of the pulse accumulator and how to use interrupts with the timer module. Stay tuned!


 

List Of Tools and Documentation

Here are links and instructions for getting 68HC12 resources

Tools

as12 assembler is available from Karl Lunt, and is the freeware assembler for the HC12 family.

SBasic is Karl Lunts version of BASIC for the 68HC12. This is a good high level language.

Robotic and Microcontrollers Products is my page that allows you to order the SRS 68HC812A4 Development board, as well as my BDM12 interface board, and the new 68HC912B32 development board.

Imagecraft has a great C compiler for the 68HC12. The compiler runs around $150, but is a great bargin if you would like to write software in C for the HC12.

Documentation (online versions)

You can get online versions of the 68HC12 documentation from Motorolas website. Here are the files to grab. You can also get printed versions as described below.

CPU12RM-AD Index is an index to a series of .PDF files that create the Motorola CPU12 Reference Manual. This describes the instruction set and programming model for the chip. It is definitely a must have. There is also an Online Version at CPU12RM-AD or http://www.mcu.motsps.com/lit/manuals/cpu12/outline1.html

a4.pdf is the .PDF file of the 68HC812A4 Technical Summary that contains information specific to the 68HC812A4 version of the chip. This is the one with 4k of EEPROM, 1k RAM, and tons of I/O. This explains all of the systems on the chip, where the registers are, etc. You should definitely have one of these if you are using the 68HC812A4.

a4-ec.pdf
(250K bytes)
is a PDF file with the electrical characteristics of the 68HC812A4. Timing diagrams, electrical capacities and absolutes, accuracies, etc.

b32ts.pdf is the .PDF file of the 68HC912B32 Technical Summary that contains information specific to the 68HC912B32 version of the chip. This is the one with 32k of Flash, 768 bytes EEPROM, 1k RAM, and still lots of I/O. This explains all of the systems on the chip, where the registers are, etc. You should definitely have one of these if you are using the 68HC912B32.

b32-ec.pdf
(272K bytes)
is a PDF file with the electrical characteristics of the 68HC912B32. Timing diagrams, electrical capacities and absolutes, accuracies, etc.

Printed Versions

Motorola will also allow you to order printed documentation online at http://design-net.com/home2/lit_ord.html where you will find a form to fill out your name and address, then a spot on the bottom for document numbers. The following are the documents that you might be interested in

CPU12RM/AD The CPU12 Reference Manual (Must Have)
MC68HC812A4EC/D 68HC812A4 Electrical Characteristics
MC68HC812A4PP/D 68HC812A4 Product Preview (Not worth the effort!)
MC68HC812A4TS/D 68HC812A4 Technical Summary (Must Have)
MC68HC912B32ECD 68HC912B32 Electrical Characteristics
MC68HC912B32PPD 68HC912B32 Product Preview (Not worth the effort!)
MC68HC912B32TSD 68HC912B32 Technical Summary (Must Have)