Path: Home => AVR overview => Applications => ATtiny with crystals
Tiny XTAL oscillator Applications of
AVR single chip controllers AT90S, ATtiny, ATmega and ATxmega
To clock an ATtiny with a crystal
Logo

ATtiny with a crystal

A simple task: an ATtiny is to be clocked with an external crystal instead of using the inaccurate internal RC oscillaor as clock source. And: from that clock source an accurate rectangle with a desired frequency shall be generated. A simple task, but there are many hurdles and things you can do wrong or that do not work as desired. Here are some hints how to do that.

CMOS version of the crystal divider And that would be such a crystal divider without a microcontroller. Designed to divide a crystal of 15 MHz by 68: In total three 14 pin ICs are necessary and 42 pins have to be handled.

The ATtiny25 microcontroller version, doing exactly the same, fits into one single 8-pin IC, of which only six have to be handled. The whole design is inside the controller, which is brought to perform all that by a few lines of assembler code.

1 An xtal controlled rectangle generator

You need to have an accurate rectangle swing? Simple, just do that:
  1. To clock an ATtiny with an external crystal.
  2. Use an internal timer/counter in CTC mode (Clear Timer on Compare) and divide the clock by an integer value.
  3. Write this divider, minus 1, to the compare register(s) of the timer, with an 8 bit timer to Compare A, with a 16 bit timer either to compare A or to the ICR (Input Capture Register).
  4. Configure the output pins OCnA and/or OCnB to toggle on Compare Matches.
  5. Configure the output pins OCnA and/or OCnB as outputs by setting their data direction bits.
  6. Start the timer by writing the prescaler bits to TCCR0B.
Nothing else has to be done, no interrupts or any additional code to be executed, so set the controller to sleep or run into an indefinite loop. The timer/counter takes over the control and generates a nice and accurate rectangle swing.

From one single crystal diverse frequencies can be derived in that way. And very flexible: just change the divider. With the OpenOffice spreadsheet here all different crystals available commercially can be examined: Cells with "-" mark impossible combinations.

If cell E6 resp. J6 is 0.00, then the exact desired frequency can be generated with at least one crystal. Which one(s) that are (and the one with the smallest difference, if none is exactly zero) can be seen from the green colored differences in columns E resp. J. Crystals with less than 0.1% difference to the desired frequency are displayed with a yellow background.

Ensure that you subtract one from the CTC divider value before writing that to the compare register of the timer/counter.

2 The hardware

Schematic of the crystal oscillator/divider This is the complete hardware. The two ceramic capacitors of 18 pF are in any case necessary to ensure that the crystal swings.

The output signal is available on PB0 (OC0A) and, if so desired and programmed, on PB1 (OC0B). Both outputs can be inversely phased or can be phased to a different angle.

In practice, and with a 15 MHz crystal attached, the crystal did only start below an operating voltage of 4 V. Above that the crystal started for a few clock cycles but then stopped working. This did not change if I divided the XTAL2 output pin voltage by two resistors before feeding the xtal. If the oscillator runs at e.g. 2.7 V, an increase of the operating voltage to above 4 V (up to 5.5 V) did not stop the oscillation. So it is a simple start-up issue. If you use an operating voltage of 5 V, make sure that the ATtiny is at 3.3 V or below, e.g. with a resistor, a Zener diode and an electrolytical capacitor. Or prepare a special solution to ensure that the oscillator swing is stable before increasing the operating voltage.

I did not find any similar reports of that kind of buggy hardware. Fortunately I had a large capacitor attached, so I saw a few of the initial swings. Depending from the number of instructions already executed the portpins OCR0A and OCR0B were either outputs or not. An error like this can drive you crazy, so do not expect hardware to work as planned, desired and as described in the device's databook.

An additional hint for the use of a trim capacitor to alter the crystal's frequency slightly. This works only on the XTAL1 input. Do not expect a large effect, only a few Hz and less than 1 kHz can be reached. Increasing capacitor values lead to increasing frequencies, at least with my 15 MHz crystal. Attention: a too large cap can stop the crystal from swinging.

3 Altering the fuses

By default the ATtiny works with its internal RC oscillator, divided by 8. To enable the external crystal, the fuses have to be changed as follows:
  1. CLKOUT must be enabled in any case, whatever crystal is used!
  2. CLKDIV8 have to be switched off, only leave that fuse set if you really want to divide the crystal frequency by 8.
  3. CLKSEL has to be changed to either a Low-Speed external crystal (e.g. with 32.768 kHz) or to an external crystal oscillator. Even though there is no external crystal oscillator attached but only a crystal. The menu of ATMEL's studio lists no opportunity to select an external crystal alone. But with CLKOUT set it works. The menu entries are confusing, just because they allow a low-speed crystal without noting that the CLKOUT fuse has to be set, but don't list external crystal attachment. The separation of the CLKOUT fuse causes the confusion here and can trigger situations with an unreachable ATtiny.
Special care has to be taken if you use a 32.768 kHz crystal. Prior to this fuse change ensure the following single steps:
  1. Reduce the ISP frequency to below 8 kHz. If your programmer has no such option, give up at that early point.
  2. Enable the CLKOUT fuse.
  3. Disable the CLKDIV8 fuse.
  4. Select the low-speed external crystal option with a long start-up procedure.
An additional issue is that the Studio denies to program flash or EEPROM with ISP frequencies below 5 kHz. As STK500 clones do not offer an ISP frequency between 5 and 8 kHz you'll not be able to program the ATtiny. AVRISP-MKII clones offer 6 kHz, which is fine.

4 Software and downloads

The assembler software can be downloaded from here. The listing is documented below.

Additionally the following OpenOffice documents can be downloaded: The source code:

;
; *********************************
; * Xtal oscillator with ATtiny25 *
; * (C)2019 by DG4FAC             *
; *********************************
;
.nolist
.include "tn25def.inc" ; Define device ATtiny25
.list
;
; **********************************
;         H A R D W A R E
; **********************************
;
; Device: ATtiny25, Package: 8-pin-PDIP_SOIC
;
;            _________
;         1 /         |8
; RESET o--|RESET  VCC|--o +5 V
; XTAL1 o--|PB3    PB2|--o
; XTAL2 o--|PB4    PB1|--o Osc out 2
;   0 V o--|GND    PB0|--o Osc out 1
;         4|__________|5
;
;
; **********************************
;  A D J U S T A B L E   C O N S T
; **********************************
;
.equ clock = 15000000 ; 15 MHz, your xtal frequency
.equ fOut = 100 ; Your desired frequency
.equ cClkPresc = 1 ; Your clock prescaler value 
.equ cUseOC0B = 1 ; Use OC0B as reverse output
;
; **********************************
;   F I X E D   C O N S T A N T S
; **********************************
;
; Derive prescaler value from clock and frequency
.if (clock/fOut/cClkPresc/2)<=256
  .equ cPresc=1
  .equ cCsPresc=1
  .else
  .if (clock/fOut/cClkPresc/2/8)<=256
    .equ cPresc=8
    .equ cCsPresc=2
    .else
    .if (clock/fOut/cClkPresc/2/64)<=256
      .equ cPresc=64
      .equ cCsPresc=3
      .else
      .if (clock/fOut/cClkPresc/2/256)<=256
        .equ cPresc=256
        .equ cCsPresc=4
        .else
        .if (clock/fOut/cClkPresc/2/1024)>256
          .error "Desired frequency too low!"
          .else
          .equ cPresc=1024
          .equ cCsPresc=5
          .endif
        .endif
      .endif
    .endif
  .endif
;
; Derive divider and compare value
.equ divider = (((((clock+fout/2)/fOut+cClkPresc/2)/cClkPresc+cPresc/2)/cPresc)+1)/2
.equ cCtc = divider - 1 ; CTC value
;
; **********************************
;        R E G I S T E R S
; **********************************
;
.def rmp = R16 ; Multipurpose register
;
; **********************************
;  M A I N   P R O G R A M   I N I T
; **********************************
;
.cseg
.org 000000
;
Main:
  sbi DDRB,DDB0 ; PB0 direction output
  cbi PORTB,PORTB0 ; Clear OC0A output
  ldi rmp,cCtc ; Write CTC value
  out OCR0A,rmp ; to compare register A
  .if cUseOC0B == 1
    sbi DDRB,DDB1 ; PB1 direction output
    sbi PORTB,PORTB1 ; Set OC0B output
    out OCR0B,rmp ; and B
    ldi rmp,(1<<WGM01)|(1<<COM0A0)|(1<<COM0B0) ; CTC mode, toggle OC0A and OC0B
    .else
    ldi rmp,(1<<WGM01)|(1<<COM0A0) ; CTC mode, toggle OC0A
    .endif
  out TCCR0A,rmp ; in TC0 control port A
  ldi rmp,cCsPresc ; Prescaler setting
  out TCCR0B,rmp ; in TC0 control port B
  ldi rmp,1<<SE ; Sleep enable, idle mode
  out MCUCR,rmp
Loop:
  sleep ; Go to sleep
  rjmp loop
;
; End of source code                

15MHz crystal generates 100 Hz This is a simulation with the above listed software setting.


©2019 by http://www.avr-asm-tutorial.net