00001 /* This file has been prepared for Doxygen automatic documentation generation.*/ 00052 // Include files 00053 #include "RC_calib_oscsampleif.h" 00054 #include "ATmega8HVA_16HVA_signature.h" 00055 #include "main.h" 00056 00057 // File global variables 00059 uint16_t temp_sensor_coeff; 00060 00061 00062 00063 void main (void) 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 } 00138 00139 00147 int8_t ReadButtons(void) 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 } 00172 00173 00174 00185 int8_t InitBandgap(void) 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 } 00233 00234 00235 00247 uint16_t MeasureTemperature(void) 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 }
1.5.5