Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C Programming for microcontrollers (Joe Pardue, 2005).pdf
Скачиваний:
260
Добавлен:
12.08.2013
Размер:
4.55 Mб
Скачать

Chapter 7: Microcontroller Interrupts and Timers

Calibrating the Butterfly oscillator:

We first used the OSCCAL_calibration() function in the PC_Comm project, claiming that we would explain it later. Well, it’s later and, wow, it’s time to understand how it works.

If you try to tell time with the uncalibrated oscillator built into the ATmega169, you can expect to gain or lose a couple of hours a day. These oscillators produce very precise pulse trains, but due to manufacturing variables, the pulse timing varies from chip to chip and do not correlate to ‘real’ time. Real time is determined by the National Bureau of Standards and references an atomic clock. To calibrate the built-in oscillator to real time requires an external crystal that has been precisely trimmed to pulse in time with the NBS clock. The Butterfly uses an external 32.768 kHz watch crystal to calibrate the oscillator to run at 8 MHz. Watch crystals are accurate, cheap, and make keeping human time easy (‘easy’ being another relative term).

We can get an accurate count of a time period by counting pulses from the watch crystal. For instance if we count 32768 pulses we know that one second has passed. We use a shorter known good period to calibrate the internal oscillator by setting the oscillator to generate x pulses in the known good time period. Remember that the oscillator is running at about 8 MHz, so we are going to get a lot more counts from it than we will get from the watch crystal. If we count 32768 pulses from the watch crystal and 8 million pulses from the oscillator in the same period, we know the 8 MHz is accurate. That is, we get 8 million counts from the oscillator in the same period we get 32768 counts (one second) from the crystal meaning the oscillator is running at exactly 8 million pulses per second. But we will actually use a much shorter period and have smaller counts. If the oscillator count is too small for the period we change the value in a register to speed it up, and if it is too large we change the register to slow it down. We do this in a loop to keep bracketing the speed until it gets as accurate as we can make it. Sounds easy, but as you’ll quickly see, it is a real pain just to get the registers all set up properly.

In this section we will learn how the Butterfly oscillator is calibrated. This is presented in two sections, the first shows the OSCCAL_calibration function, and the second gives a detailed explanation.

121

Chapter 7: Microcontroller Interrupts and Timers

OSCCAL_calibration() function – the code:

/*******************************************************************

*

* Function name : OSCCAL_calibration

*

None

* Returns :

*

 

*Parameters : None

*Purpose : Calibrate the internal OSCCAL byte, using the external

*

32,768 kHz crystal as reference

*

 

 

*******************************************************************/

void OSCCAL_calibration(void)

{

 

 

unsigned char calibrate = FALSE;

int temp;

 

 

unsigned char tempL;

 

CLKPR = (1<<CLKPCE);

// set Clock Prescaler Change Enable

// set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz

CLKPR = (1<<CLKPS1)

| (1<<CLKPS0);

TIMSK2 = 0;

//disable OCIE2A and TOIE2

ASSR =

(1<<AS2);

//select asynchronous operation of timer2

 

 

(32,768kHz)

OCR2A = 200;

// set timer2 compare value

TIMSK0 = 0;

// delete any interrupt sources

TCCR1B = (1<<CS10);

// start timer1 with no prescaling

TCCR2A = (1<<CS20);

// start timer2 with no prescaling

//wait for TCN2UB and TCR2UB to clear

while((ASSR & 0x01) | (ASSR

& 0x04));

Delay(1000);

// wait for

external crystal to stabilise

while(!calibrate)

{

cli(); // mt __disable_interrupt(); // disable global interrupt

TIFR1

=

0xFF;

//

delete

TIFR1

flags

TIFR2

=

0xFF;

//

delete

TIFR2

flags

122