Trimming the Internal Clock Generator on the 68HC908KX8 Microcontroller

One of the nicest features of the 8-bit KX8 microcontroller (manufactured by Freescale Semiconductor) is that it includes an internal clock generator (ICG). This allows the chip to run without the trouble and expense of an external crystal or canned oscillator.

The downside is that the built-in oscillator can be pretty inaccurate. Theoretically, the frequency could be off by up to 25% on an untrimmed chip (worst case). If you test the individual chip and place its specific trim value into the code, then the base frequency may be as accurate as 0.3% when averaging combined pulses (best case). (For more information, see the MC68HC908KX8 datasheet or AN2498 technical notes.)

Realistically, if you need better than 1% accuracy you should probably use a crystal.

I use the 16-pin DIP KX8 as the primary brain for many of my robots. In particular, I use that microcontroller in Roundabout, the robot from the book Intermediate Robot Building.

I decided to make pre-programmed microcontrollers available for readers that want to reproduce Roundabout but don’t have a programming board for installing the downloadable HC08 source code (see the link in Appendix A of the book). Since Roundabout plays music during operation, reasonably accurate frequency is important for the notes to be in tune. So, that meant that I needed to know the best trim value for the internal clock generator of each individual chip before programming.

Manual Trimming

In the past, when I was only trimming one or two MCUs a year, I’d simply hand tune them.

  1. Using code, stuff the default trim value (80 hex) into the ICG.
  2. Have the code output a regular pulse on one of the pins, say every 1/4 second.
  3. Connect an oscilloscope or multimeter in frequency mode to measure the output.
  4. Raise or lower the trim value in the code -- guessing magnitude based on how far off the frequency measured.
  5. Recompile and then reprogram the chip.
  6. Repeat until the measured output frequency is close enough for the intended purpose of that chip.

I had no interest in performing these steps for hundreds of chips.

Automatic Trimming

The process I am about to describe could be better optimized for assembly lines where time is money. Nonetheless, here’s an automated technique that works acceptably well for small lots (a few hundred chips).

1. Start with a high-quality canned oscillator with a frequency that is a power of 2. For example, 32.768 MHz. Although it isn’t absolutely necessary for it to be a power of 2, that makes it easy for a microcontroller to shift or divide down to human-friendly rates per second.

2. Connect the canned oscillator to a microcontroller that can divide it down to a slower pulse. I used the built-in pulse-width modulator (PWM) on another KX8 to output a signal of 2 Hz (0.5 seconds) with a 50% duty cycle. You want the pulse to be as long as possible to improve the accuracy of the measurement, but not so long as to put you to sleep waiting for the target microcontroller to trim itself.

Note that this KX8 doesn’t need to be trimmed because it isn’t using its internal oscillator. This KX8 is run by the canned oscillator with a highly accurate crystal.

If you think using one KX8 to trim another KX8 is a bit strange, an alternate suggestion is to select a slower canned oscillator and use a 74HC4020 or 74HC4040 binary ripple counter logic chip as a divider.

3. Connect an oscilloscope or multimeter in frequency mode to measure the output, just to be sure it is what you expected (2 Hz in this example). Okay, now remove the oscilloscope.

4. Install code in the target KX8 to time the 2 Hz signal. Make sure the target KX8 is given plenty of time to fully power up and stabilize (loop until the ICGS stable bit is 1). Also, don’t skimp on a variety of external capacitors to reduce spurious noise.

5. To time the signal, you can use the target KX8’s input capture module (I did) or simply loop (no COP, no interrupts) while incrementing a counter. Based on the bus speed you select for the target KX8, you should be able to manually calculate what the counter should reach for a 1/4 second half-pulse. (The input pin will go high and then low, so we’re measuring half of a 2 Hz wave.)

For example, I chose a target ICG bus of 7.9872 MHz with a input capture divider of 64 for an input capture bus of 124.8 kHz Which means that if the target ICG is perfectly trimmed that the count should be:

124.8 kHz / ( 2 Hz (signal) * 2 (half pulse) ) = 31200

6. At the end of the half pulse, if the count is too high, then the target’s ICG is too fast and the trim value should be increased. Weird huh? The trim value engages tiny capacitors. The more capacitors engaged the longer they take to charge and discharge, thus the slower the internal clock. In other words, lower trim values produce a faster oscillating frequency.

On the other hand, if the half-pulse count is too low, then the target’s ICG is too slow, and the trim value should be decreased, reducing the number of tiny capacitors, and thus increasing the target ICG’s frequency.

7. You’ve got a variety of choices on how much to increase or decrease the trim value. The simplest method is to increase or decrease by 1, which is sure to find the correct trim value but will take the longest. To speed up the guessing process I used a binary search with a middle pivot point, but this wasn’t the fastest choice since the algorithm should be able to make a more educated guess as to the midpoint based on how far off the count is.

8. Compare the current guess count to the best guess so far. If the current guess is the best, remember the absolute value of how close it came and the trim value tried. It is rare for the count to ever be perfect, so you want to keep track of the best match.

9. For single step searches, repeat until your current guess is worse than your best guess so far or (for binary searches) repeat until your minimum trim guess and maximum trim guess meet or cross (min >= max).

10. When the final “best” trim value is discovered, you'll want to show the trim number somehow. A serial port might be a good choice since the baud rate is now fairly accurate.

I chose to use a pair of 74HC595 shift registers connected to 7-segment numeric LEDs. At room temperature and 5 V, the 74HC595s can operate anywhere from 0 Hz to 30 MHz. Unlike a serial port’s baud rate, the 74HC595 doesn’t need a consistent or preselected clock rate. So, the trim value being tested can be displayed at all times during the guessing process, even when the target ICG’s frequency is inaccurate.

A solderless breadboard containing a known clock source, divider, LED display, and target KX8 to be trimmed. Click to see a movie of the target KX8 trimming itself.

Click to see a video of a MC68HC908KX8 getting trimmed.

The trimming process is fun to watch and takes about 10 seconds (unoptimized). The little red (top-center) and yellow (bottom-center) LEDs indicate whether a guess is too high or too low. The little green LED (top-center next to the red LED) indicates that the best trim value has been found and that the process is now complete.

I added a pushbutton to repeat the test without cycling power. After repeating the test multiple times on the same target microcontroller, sometimes the best trim value will go up or down by one number. Remember, the internal oscillator isn’t very accurate even when trimmed, and can vary enough for either of two adjoining trim values to be legitimately “best” from test to test.

Trim Distribution

I had two batches of MC68HC908KX8CP microcontrollers on hand for testing. 21 had a date code of 0035 (mask 1K45D) and 100 had a date code of 0403 (mask 2L09H). They were trimmed at room temperature all on the same day. About 10% were randomly retested at the end, and all were reconfirmed to be within 1 of the originally determined trim value.

A bar chart of the trim values of a 121 sample lot of two batches of MC68HC908KX8 microcontrollers.

A bar chart of the trim values of a 121 sample lot of two batches of MC68HC908KX8 microcontrollers.

Note: Decimal quantity on the vertical axis. Trim values in hexadecimal on the horizontal axis. Data code 0035 batch in red.

As you can see, the trim values varied considerably from chip to chip and batch to batch, with some moderate clumping towards to center. Values ranged from $4F to $B5. Only 16% of the microcontrollers reasonably matched (+/- 1) the default $80 trim value.


The internal clock generator is a wonderful feature for convenience, reduced cost, reduced board space, and as a backup to a more accurate clock source. With a little work, the ICG can easily be trimmed (manually or automatically) to within a couple of percent accuracy over time (not pulse-to-pulse).

Based on the variations in internal oscillator speeds as shown in the test results, it is worth trimming the microcontroller.