main.c File Reference


Detailed Description

main.c, demonstration of using runtime oscillator calibration.

Demonstration of Slow RC period calculation, Fast RC calibration and Ultra Low Power RC period measurement. Slow RC is used for calibrating the Fast RC and measuring ULP RC period.

Application note:
AVR351: Runtime calibration and compensation of RC oscillators using the Oscillator Sampling Interface
Documentation
For comprehensive code documentation, supported compilers, compiler settings and supported devices see readme.html
Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Revision
4809
Date
2008-11-04 12:17:59 +0100 (ti, 04 nov 2008)

Copyright (c) 2008, Atmel Corporation All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. The name of ATMEL may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Definition in file main.c.

#include "RC_calib_oscsampleif.h"
#include "ATmega8HVA_16HVA_signature.h"
#include "main.h"

Include dependency graph for main.c:

Go to the source code of this file.

Functions

int8_t InitBandgap (void)
 Bandgap initialisation.
void main (void)
uint16_t MeasureTemperature (void)
 Temperature measurement.
int8_t ReadButtons (void)
 Read what/if buttons was pressed.

Variables

uint16_t temp_sensor_coeff
 < For calculating temperature from VPTAT measurement (internal temperature sensor)


Function Documentation

int8_t InitBandgap ( void   ) 

Bandgap initialisation.

Initialises the bandgap voltage reference to factory calibration. If second calibration has been done at room temperature those values are loaded. BGCCR need to be changed slowly to avoid BOD. See appnote for details.

Return values:
FAILED Loading of signature data failed.
ROOM_TEMPERATURE Signature data for second insertion test found.
HOT_TEMPERATURE Signature data only for first insertion test found.

< Factory calibration of BGCCR and BGCRR.

Definition at line 185 of file main.c.

References BANDGAP_ADJ_DELAY, FAILED, HOT_TEMPERATURE, READ_SIGNATUREBYTE, ROOM_TEMPERATURE, SIG_BGCCR_CALIB_25C, SIG_BGCCR_CALIB_HOT, and SIG_BGCRR_CALIB_25C.

Referenced by main().

00186 {
00188     uint8_t bgccr_cal, bgcrr_cal;
00189     int8_t  mode;
00190 
00191     bgcrr_cal = READ_SIGNATUREBYTE(SIG_BGCRR_CALIB_25C);
00192     
00193     /* Uncomment the following line to do second point calibration. Please notice
00194      * that breaking within 2 cycles of completing a signature byte reading will 
00195      * corrupt AVR Studio flash readout.
00196      */
00197 //  bgcrr_cal = 0xFF;
00198     
00199     // Check that valid BGCRR data exists in the signature row.
00200     if ( bgcrr_cal != 0xFF ){
00201         bgccr_cal = 0x3F & READ_SIGNATUREBYTE(SIG_BGCCR_CALIB_25C); 
00202         mode = ROOM_TEMPERATURE;
00203     }else{
00204         // No valid data was found. Load HOT temperature data and abort if that is not valid.
00205         bgcrr_cal = 0x0F;
00206         bgccr_cal = 0x3F & READ_SIGNATUREBYTE(SIG_BGCCR_CALIB_HOT);
00207         
00208         if (bgccr_cal == 0x3F) {
00209             return FAILED;
00210         }
00211         
00212         mode = HOT_TEMPERATURE;
00213     }       
00214 
00215     BGCRR = bgcrr_cal;
00216 
00217     // If done this way device may enter BOD so use method below.
00218     // BGCCR = bgccr_cal;               
00219     
00220     // Adjust BGCCR up if needed. Slowly to avoid BOD.
00221     while (BGCCR < bgccr_cal) {
00222         BGCCR++;
00223         __delay_cycles(BANDGAP_ADJ_DELAY);
00224     }
00225     
00226     /* Adjust down if necessary. (Safe with regard to BOD, but uses
00227      * longer time to stabilize and thus give correct ADC measurements)
00228      */
00229     BGCCR = bgccr_cal;
00230                                       
00231     return mode;
00232 }

void main ( void   ) 

< Volatile to avoid compiler warning, since we are only storing it.

Definition at line 63 of file main.c.

References BUTTON_ONE, BUTTON_THREE, BUTTON_TWO, CalculateSlowRCperiod(), CalibrateFastRCruntime(), HOT_TEMPERATURE, InitBandgap(), MeasureTemperature(), MeasureULPRCperiod(), READ_SIGNATUREBYTE, ReadButtons(), ROOM_TEMPERATURE, SIG_VPTAT_H, SIG_VPTAT_L, SUCCESS, TEMP_DIFF_LIMIT, temp_sensor_coeff, and ZERO_C_IN_KELVIN.

00064 {
00065     uint16_t current_temperature, calibration_temperature;
00066     int16_t  temp_diff;
00067     uint16_t slow_RC_period;
00068     
00070     volatile uint16_t ULP_RC_period;
00071     
00072     int8_t   button_pressed;
00073 
00074     /* Calibrate bandgap reference. This checks if signature row contains
00075      * data from second insertion. No check for failure is implemented.
00076      */
00077     if (InitBandgap() == ROOM_TEMPERATURE){ 
00078         // Fast RC calibrated at room temperature.
00079         calibration_temperature = ZERO_C_IN_KELVIN + ROOM_TEMPERATURE;
00080     }else{
00081         // Fast RC calibrated at hot temperature.
00082         calibration_temperature = ZERO_C_IN_KELVIN + HOT_TEMPERATURE;
00083     }
00084     
00085     // Read temperature sensor coefficient from signature row and store in global variable.
00086     temp_sensor_coeff =  READ_SIGNATUREBYTE(SIG_VPTAT_L);
00087     
00088     // Avoid writing to SPMCSR register within 6 cycles of previous write.
00089     __delay_cycles(2);
00090 
00091     temp_sensor_coeff |= (READ_SIGNATUREBYTE(SIG_VPTAT_H) << 8);
00092 
00093     // Output System clock/2 on PINB0 to enable easy debugging.
00094     DDRB |= (1 << DDB0);
00095     MCUCR |= (1 << CKOE);
00096 
00097     // Enter eternal loop.
00098     do {
00099         /* In an actual application the temperature measurements would
00100          * be part of the, possibly interrupt driven, VADC measurement
00101          * but here we just manually sample them.
00102          */
00103         current_temperature = MeasureTemperature();
00104         temp_diff = current_temperature - calibration_temperature;
00105         button_pressed = ReadButtons();
00106 
00107         // Start calibration if called for, either by temperature difference or button 3 (PB3).
00108         if ( (temp_diff > TEMP_DIFF_LIMIT) || (temp_diff < -TEMP_DIFF_LIMIT) || (button_pressed == BUTTON_THREE) ) {
00109 
00110             slow_RC_period = CalculateSlowRCperiod(current_temperature);
00111             ULP_RC_period = MeasureULPRCperiod(slow_RC_period);
00112 
00113             /* Here we use the The Slow RC result for ULP RC period measurement and Fast RC calibration.
00114              * In a battery application the Slow RC or ULP RC period would also be used for compensating
00115              * the Coulomb counter ADC results. Please see application note AVR352 for details.
00116              */
00117 
00118             if (CalibrateFastRCruntime(slow_RC_period) == SUCCESS){
00119                 // Save the temperature we calibrated at.
00120                 calibration_temperature = current_temperature;
00121             }else{
00122                 // Should flag error here. No action is taken in this application. 
00123             }
00124         }
00125         
00126         // Adjust FOSCCAL down if button 1 is pressed (PB1), thus decreasing clock frequency.
00127         if (button_pressed == BUTTON_ONE){
00128             FOSCCAL--;      
00129         }
00130         
00131         // Adjust FOSCCAL up if button 2 is pressed (PB2), thus increasing clock frequency.
00132         if (button_pressed == BUTTON_TWO){
00133             FOSCCAL++;      
00134         }
00135         
00136     } while(1);
00137 }

Here is the call graph for this function:

uint16_t MeasureTemperature ( void   ) 

Temperature measurement.

Returns temperature in Kelvin (uint16_t). Absolute accuracy of the temperature sensor is stated at +/-5 Kelvin in the data sheet.

An alternative could be to use °C with 1 byte signed format, thus giving a range of +127 - -128°C. In an application temperature measurements should be part of the VADC interrupt controlled measurements.

Returns:
temperature [Kelvin] (uint16_t)

Definition at line 247 of file main.c.

References temp_sensor_coeff, and VTEMP.

Referenced by main().

00248 {
00249     uint32_t temperature;
00250     
00251     // VTEMP as input
00252     VADMUX = VTEMP;
00253     
00254     temperature = VADC;
00255 
00256     // Enable VADC and start conversion
00257     VADCSR = (1 << VADEN) | (1 << VADSC) | (1 << VADCCIF);
00258 
00259     do {} while(!(VADCSR & (1 << VADCCIF)));
00260     
00261     temperature = VADC;
00262     temperature *= temp_sensor_coeff;
00263 
00264     // Disable VADC and reset interrupt flag, interrupting any ongoing conversion
00265     VADCSR = (1 << VADCCIF);
00266     return ((uint16_t)(temperature >> 14));
00267 }

int8_t ReadButtons ( void   ) 

Read what/if buttons was pressed.

Uses PB1/2/3 as inputs, so they must be configured as inputs (default when device is reset). Waits for button(s) to be released before returning the result.

Returns:
Which button was pressed, or FAILED if none or multiple was pressed.

Definition at line 147 of file main.c.

References BUTTON_MASK, BUTTON_ONE, BUTTON_THREE, BUTTON_TWO, and FAILED.

Referenced by main().

00148 {
00149     uint8_t buttons_pressed;
00150     int8_t return_value;
00151     buttons_pressed = (~PINB & BUTTON_MASK);
00152     
00153     do {} while (~PINB & BUTTON_MASK);
00154     
00155     switch( buttons_pressed ) {
00156         case (1 << BUTTON_ONE):
00157             return_value = BUTTON_ONE;
00158             break;
00159         case (1 << BUTTON_TWO):
00160             return_value = BUTTON_TWO;
00161             break;
00162         case (1 << BUTTON_THREE):
00163             return_value = BUTTON_THREE;
00164             break;
00165         default : 
00166             return_value = FAILED;
00167             break;
00168     }
00169     
00170     return return_value;
00171 }


Variable Documentation

< For calculating temperature from VPTAT measurement (internal temperature sensor)

Definition at line 59 of file main.c.

Referenced by main(), and MeasureTemperature().


Generated on Tue Nov 4 14:58:58 2008 for AVR351 Runtime calibration and compensation of oscillators by  doxygen 1.5.5