Tuesday, July 28, 2015

Externally clocking (and overclocking) AVR MCUs

People familiar with AVR boards such as Arduinos likely know most AVR MCUs can be clocked from an external crystal connected to 2 of the pins.  When the AVR does not need to run at a precise clock frequency, it is also common to clock them from the internal 8Mhz oscillator.  Before CPUs were made with internal oscillators or inverting amplifiers for external crystals, they were clocked by an external circuit.  Although you won't see many AVR projects doing this, every AVR I have used supports an external clock option.  One (extreme) example of a project using an external clock is Brad's Quark85 video game platform.  Some AVRs such as the tiny13a and the tiny88 do not support an external crystal, so the internal oscillator or an external clock circuit are the only options.  The 4-pin metal can pictured above is a clock circuit hermetically sealed for precision and stability.  They can be bought from Asian sources for under $2.

A common reason for needing an external clock for an AVR MCU is from accidentally setting the fuses for an external clock.  Once the fuses are set to external clock, they cannot be reprogrammed without providing an external clock signal.  Wiring the oscillator is simple; connect power and ground, then connect the output to the CLKI pin of the MCU.   On the ATtiny13a, this is pin 2 (PB3).  On the ATmega328-AU, this is pin 7 (PB6).

The output of the oscillators is very stable and accurate, around a few ppm, as measured by my Rigol scope.  The output is almost rail-to-rail (0-5V), and quite clean:

Although the connection is simple, it's not foolproof.  During my experimentation, I accidentally plugged my oscillator backwards (connecting 5V to Gnd and Gnd to 5V), which quickly fried it.  Now I'll be extra careful with the M-Tron 40Mhz oscillator so I don't kill that too!

AVRs are known for being easy to overclock, but I was uncertain whether an ATtiny13a rated for 20Mhz would work when overclocked to more than double it's rated speed.  I experienced no problems flashing code with avrdude and running my bit-bang UART at either 40 or 44.3Mhz with a 5V supply.  At 3.3V it crashed most of the time, only running OK occasionally.

Another way to provide an external clock is to build a ring oscillator using a 7404 hex inverter or similar chip.  A 3-stage ring oscillator I build using a 7404 generated a clock close to 30Mhz:

Since the frequency is inversely proportional to the number of stages, a 5-stage oscillator using the same 7404 would generate a frequency of 18Mhz.  I tried to make a single-stage oscillator with the 7404 and also with a 74LS00, but was unsuccessful,  They are just not fast enough to generate a 90Mhz clock.  Considering the 7404 I used is a Fairchild part with a 1984 date stamp, I'm pleased with how well this 30-year-old part works.

The last way of getting a clock source I'll describe is to tap off the XTAL pin of an AVR (or other MCU) that is using an external crystal.  Most AVRs can drive the external crystal in low-power of full-swing mode.  For the ATmega8a, the CKOPT fuse enables full swing mode.  If the AVR is driving the crystal in low-power mode, the peak-to-peak voltage will not be enough to work as the external clock for another AVR.  By soldering a wire to one of the XTAL pins you can use it to clock another MCU.  I've labeled the XTAL pins in yellow on a chinese USBasp clone:

And here's a shot from my scope connected to the 12Mhz crystal on the USBasp:

Finally, if your external clock is slower than 8Mhz (like if you were to use a 555 timer to generate the clock) you'll probably need to use a slower SPI bit clock setting with avrdude.  I've found avrdude -B 4, specifying a 4 microsecond clock period will work with AVRs clocked as low as 1Mhz.

1 comment: