This contain functions for reading out signature row data, bandgap initialisation and bandgap calibration. Functions for start of VADC measurements, interrupt routine for measurements and calculation of cell voltages, vadc inputs and bandgap temperature are also included.
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 vadc_usage.c.
#include <ioavr.h>
#include <inavr.h>
#include "vadc_usage.h"
#include "calibration.h"
#include "ATmega8HVA_16HVA_signature.h"

Go to the source code of this file.
Defines | |
| #define | module_vadc_usage 1 |
| < Define for vadc_usage.h to avoid including the external variables. | |
Functions | |
| void | CalculateADCResults (void) |
| Calculate results from the VADC raw values. | |
| int8_t | CalibrateVREF (void) |
| Voltage reference calibration. | |
| int8_t | InitBandgap (void) |
| Bandgap initialisation. | |
| void | InitCoeff (void) |
| Function to load coefficients needed from the signature row. | |
| int16_t | MeasureVADCerror (void) |
| Measure VADC error. | |
| void | StartVADCScan (void) |
| Start a scan of all VADC channels. | |
| __interrupt void | VADC_ISR (void) |
| Interrupt Service Function to measure VADC values. | |
Variables | |
| uint16_t | bg_temp |
| Global variable for the result of band-gap temperature measurement/calculation. | |
| uint16_t | cell_gain [NO_CELLS] |
| Gain coefficients for Cells. | |
| int8_t | cell_offset [NO_CELLS] |
| Offset for cells. | |
| uint16_t | cell_v [NO_CELLS] |
| Global variable for results of Cell Voltage measurements/calculations. | |
| uint16_t | vadc_gain [NO_VADC] |
| VADC channel gain. | |
| uint16_t | vadc_measurement [NO_VADC_CHANNELS] |
| Global variable for VADC samples. Sized to number of VADC channels. | |
| int8_t | vadc_offset [NO_VADC] |
| VADC channel offset. | |
| uint8_t | vadc_scan_complete |
| Flag for signalling VADC sampling complete. | |
| uint16_t | vadc_v [NO_VADC] |
| Global variable for results of Voltage ADC measurements/calculations. | |
| uint16_t | vptat_coeff |
| Internal temperature sensor coefficient. | |
| #define module_vadc_usage 1 |
< Define for vadc_usage.h to avoid including the external variables.
Definition at line 54 of file vadc_usage.c.
| void CalculateADCResults | ( | void | ) |
Calculate results from the VADC raw values.
Function uses values from vadc_measurement variable and stores results in global variables cell_v and bg_temp. The formulas are found in the data sheet and details in the application note.
Definition at line 300 of file vadc_usage.c.
References bg_temp, CELL1, cell_gain, cell_offset, cell_v, NO_CELLS, NO_VADC, VADC0, vadc_gain, vadc_measurement, vadc_offset, VADC_SCALE_BITS, vadc_v, VPTAT, and vptat_coeff.
Referenced by main().
00301 { 00302 uint32_t calc; 00303 uint8_t index; 00304 00305 // Calculate new cell voltages. 00306 for(index = 0 ; index < NO_CELLS ; index++) { 00307 calc = vadc_measurement[index + CELL1]; 00308 calc -= cell_offset[index]; 00309 calc *= cell_gain[index]; 00310 cell_v[index] = (uint16_t)(calc >> VADC_SCALE_BITS); 00311 } 00312 00313 /* Code checking for under or over-voltage, and/or calculating cell 00314 * impedances could be inserted here. 00315 */ 00316 00317 // Calculate new VADC voltages. 00318 for(index = 0 ; index < NO_VADC ; index++) { 00319 calc = vadc_measurement[index + VADC0]; 00320 calc -= vadc_offset[index]; 00321 calc *= vadc_gain[index]; 00322 vadc_v[index] = (uint16_t)((calc >> VADC_SCALE_BITS)/10); 00323 } 00324 00325 // Calculate temperature from measurement of internal temp sensor (VPTAT). 00326 calc = vadc_measurement[VPTAT]; 00327 calc *= vptat_coeff; 00328 calc >>= VADC_SCALE_BITS; 00329 bg_temp = (uint16_t)(calc); 00330 00331 /* Code for calculating temperature from external thermistors connected to 00332 * VADC0 and/or VADC1 could be inserted here. Gain and offset coefficients for 00333 * vadc inputs are stored in signature row. 00334 */ 00335 }
| int8_t CalibrateVREF | ( | void | ) |
Voltage reference calibration.
Calibrates the bandgap reference. Assumes 4096mV in on PV1 (Cell1). Values in calibration.h have to be adjusted if any other value is used. The reference needs to be calibrated to factory default before performing this calibration, and if it fails the reference is not correct and factory defaults should be used.
Calibration of bandgap at room temperature only needs to be done if device isn't calibrated so in Atmel factory. Otherwise calibration can be done by reading out signature data.
Definition at line 353 of file vadc_usage.c.
References CAL_CHANNEL, FAILED, MeasureVADCerror(), SUCCESS, temp_cal, and vcalibration_level.
Referenced by main().
00354 { 00355 volatile uint32_t temp; 00356 int16_t v_error; // Variable to keep error after conversion. 00357 int16_t last_v_error; // Value used to keep old error value during linear scan. 00358 int8_t counter; // Value used to count BGCCR value and index. 00359 00360 // Select terminal input defined in calibration.h 00361 VADMUX = CAL_CHANNEL; 00362 00363 // Enable the VADC. 00364 VADCSR = (1 << VADEN); 00365 00366 // Start a VADC conversion and clear any pending interrupts 00367 VADCSR |= (1 << VADSC) | (1 << VADCCIF); 00368 00369 // Wait while conversion in progress 00370 do {} while(!(VADCSR & (1 << VADCCIF))); 00371 00372 // Dummy read to ensure correct data for next conversion. 00373 temp = VADC; 00374 00375 00376 /* If using cell balancing (e.g ATmega406, and not on ATmega8/16HVA), 00377 * code should be inserted here to wait for error to cancel out. 00378 */ 00379 00380 // First we do the BGCRR / temperature stability calibration. 00381 v_error = MeasureVADCerror(); 00382 counter = 8; 00383 00384 // Check for all different test limits. 00385 while ( (v_error < vcalibration_level[counter]) && (counter >= 0) ) { 00386 counter--; 00387 } 00388 00389 // Set BGCRR to correct setting. 00390 BGCRR = temp_cal[counter]; 00391 00392 // Then we do the BGCCR / absolute value calibration. 00393 v_error = MeasureVADCerror(); 00394 00395 if (v_error < 0){ 00396 do { 00397 // Ratio_counter bit 6 set means calibration failed. 00398 if(--BGCCR == 0x40){ 00399 // Return with fail flag. 00400 return FAILED; 00401 } 00402 last_v_error = v_error; 00403 v_error = MeasureVADCerror(); 00404 00405 } while (v_error < 0); 00406 00407 // Neighbor check, as previous step can select the next best value. 00408 if (v_error > -last_v_error){ 00409 BGCCR++; 00410 } 00411 00412 }else{ 00413 do{ 00414 // Ratio_counter bit 6 set means calibration failed. 00415 if(++BGCCR == 0x40){ 00416 // Return with fail flag. 00417 return FAILED; 00418 } 00419 last_v_error = v_error; 00420 v_error = MeasureVADCerror(); 00421 00422 } while (v_error < 0); 00423 00424 // Neighbor check, as previous step can select the next best value. 00425 if(-v_error > last_v_error){ 00426 BGCCR--; 00427 } 00428 } 00429 00430 /* The found values should be stored in eeprom or possibly flash for 00431 * correct initialisation if device is reset. 00432 */ 00433 return SUCCESS; 00434 }

| 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.
| FAILED | Loading of signature data failed. | |
| CALIB_ROOM | Signature data for second insertion test found. | |
| CALIB_HOT | Signature data only for fist insertion test found. |
< Factory calibration of BGCCR and BGCRR.
Definition at line 156 of file vadc_usage.c.
References BANDGAP_ADJ_DELAY, CALIB_HOT, CALIB_ROOM, FAILED, READ_SIGNATUREBYTE, SIG_BGCCR_CALIB_25C, SIG_BGCCR_CALIB_HOT, and SIG_BGCRR_CALIB_25C.
Referenced by main().
00157 { 00159 uint8_t bgccr_cal, bgcrr_cal; 00160 int8_t mode; 00161 00162 bgcrr_cal = READ_SIGNATUREBYTE(SIG_BGCRR_CALIB_25C); 00163 00164 #ifdef IGNORE_2ND_CAL 00165 // To do second point calibration on parts that already have. 00166 bgcrr_cal = 0xFF; 00167 #endif 00168 00169 /* Please note that breaking within 2 cycles of completing a signature byte 00170 * reading will corrupt further AVR Studio flash readout until a reset is issued. 00171 */ 00172 if ( bgcrr_cal != 0xFF ){ 00173 // Check to see if part was calibrated at room temperature. 00174 bgccr_cal = 0x3F & READ_SIGNATUREBYTE(SIG_BGCCR_CALIB_25C); 00175 mode = CALIB_ROOM; 00176 } else { 00177 bgcrr_cal = 0x0F; 00178 bgccr_cal = 0x3F & READ_SIGNATUREBYTE(SIG_BGCCR_CALIB_HOT); 00179 00180 if (bgccr_cal == 0x3F) { 00181 return FAILED; 00182 } 00183 00184 mode = CALIB_HOT; 00185 } 00186 00187 BGCRR = bgcrr_cal; 00188 00189 // If done this way device may enter BOD so use method below. 00190 // BGCCR = bgccr_cal; 00191 00192 while (BGCCR < bgccr_cal){ 00193 // Adjust BGCCR up if needed. Slowly to avoid BOD. 00194 BGCCR++; 00195 __delay_cycles(BANDGAP_ADJ_DELAY); 00196 } 00197 00198 // Adjust down if necessary. (Safe - but results in wrong ADC measurements until VREF is stabilized) 00199 BGCCR = bgccr_cal; 00200 00201 return mode; 00202 }
| void InitCoeff | ( | void | ) |
Function to load coefficients needed from the signature row.
Loads all signature data into an array and then stores the relevant ones in (file) global variables.
Definition at line 91 of file vadc_usage.c.
References cell_gain, cell_offset, READ_SIGNATUREBYTE, SIG_END_ADDRESS, SIG_VADC_ADC0_GAIN_H, SIG_VADC_ADC0_GAIN_L, SIG_VADC_ADC0_OFFSET, SIG_VADC_ADC1_GAIN_H, SIG_VADC_ADC1_GAIN_L, SIG_VADC_ADC1_OFFSET, SIG_VADC_CELL1_GAIN_H, SIG_VADC_CELL1_GAIN_L, SIG_VADC_CELL1_OFFSET, SIG_VADC_CELL2_GAIN_H, SIG_VADC_CELL2_GAIN_L, SIG_VADC_CELL2_OFFSET, SIG_VADC_RAW_ADC0_H, SIG_VADC_RAW_ADC0_L, SIG_VADC_RAW_CELL1_H, SIG_VADC_RAW_CELL1_L, SIG_VPTAT_H, SIG_VPTAT_L, vadc_gain, vadc_offset, and vptat_coeff.
Referenced by main().
00092 { 00093 uint8_t signature_array[SIG_END_ADDRESS+1]; 00094 00095 for(uint8_t i=0 ; i <= SIG_END_ADDRESS ; i++){ 00096 signature_array[i] = READ_SIGNATUREBYTE(i); 00097 } 00098 00099 /* Please note that breaking within 2 cycles of completing a signature byte 00100 * reading will corrupt further AVR Studio flash readout until a reset is issued. 00101 */ 00102 00103 // Coefficient for temperature calculation from internal sensor. 00104 vptat_coeff = signature_array[SIG_VPTAT_L]; 00105 vptat_coeff |= signature_array[SIG_VPTAT_H] << 8; 00106 00107 // Coefficients for cell gain and offset. 00108 cell_gain[0] = signature_array[SIG_VADC_CELL1_GAIN_L]; 00109 cell_gain[0] |= signature_array[SIG_VADC_CELL1_GAIN_H] << 8; 00110 cell_offset[0] = signature_array[SIG_VADC_CELL1_OFFSET]; 00111 00112 cell_gain[1] = signature_array[SIG_VADC_CELL2_GAIN_L]; 00113 cell_gain[1] |= signature_array[SIG_VADC_CELL2_GAIN_H] << 8; 00114 cell_offset[1] = signature_array[SIG_VADC_CELL2_OFFSET]; 00115 00116 // Coefficients for VADC gain and offset. 00117 vadc_gain[0] = signature_array[SIG_VADC_ADC0_GAIN_L]; 00118 vadc_gain[0] |= signature_array[SIG_VADC_ADC0_GAIN_H] << 8; 00119 vadc_offset[0] = signature_array[SIG_VADC_ADC0_OFFSET]; 00120 00121 vadc_gain[1] = signature_array[SIG_VADC_ADC1_GAIN_L]; 00122 vadc_gain[1] |= signature_array[SIG_VADC_ADC1_GAIN_H] << 8; 00123 vadc_offset[1] = signature_array[SIG_VADC_ADC1_OFFSET]; 00124 00125 // Only load raw calibration values if needed. 00126 #ifndef USE_CAL_GAIN 00127 00128 // Using Cell1 for calibration. 00129 #ifdef USE_CELL1_CAL 00130 // RAW Cell1 measurements for 4096mV in. 00131 raw_cal = signature_array[SIG_VADC_RAW_CELL1_L]; 00132 raw_cal |= signature_array[SIG_VADC_RAW_CELL1_H] << 8; 00133 00134 // Using VADC0 for calibration. 00135 #else 00136 // RAW VADC0 measurements with (4096/5)mV in. 00137 raw_cal = signature_array[SIG_VADC_RAW_ADC0_L]; 00138 raw_cal |= signature_array[SIG_VADC_RAW_ADC0_H] << 8; 00139 #endif 00140 00141 #endif 00142 00143 }
| int16_t MeasureVADCerror | ( | void | ) |
Measure VADC error.
Subroutine for measurement of VADC input and calculation of error. Uses defines from calibration.h.
Definition at line 444 of file vadc_usage.c.
References CAL_GAIN, CAL_OFFSET, VADC_SCALE_BITS, and VCALIB_VALUE.
Referenced by CalibrateVREF().
00445 { 00446 // Variable to keep error after conversion. 00447 int32_t vadc_error; 00448 00449 // Start a VADC conversion and clear any pending interrupts 00450 VADCSR |= (1 << VADSC) | (1 << VADCCIF); 00451 00452 // Wait while conversion in progress 00453 do {} while(!(VADCSR & (1 << VADCCIF))); 00454 00455 // Calculate error of VADC measurement. 00456 vadc_error = VADC; 00457 00458 #ifdef USE_CAL_GAIN 00459 vadc_error -= CAL_OFFSET; 00460 vadc_error *= CAL_GAIN; 00461 00462 // Divide by 16384. 00463 vadc_error >>= VADC_SCALE_BITS; 00464 #endif 00465 00466 vadc_error -= VCALIB_VALUE; 00467 return (int16_t) vadc_error; 00468 }
| void StartVADCScan | ( | void | ) |
Start a scan of all VADC channels.
VADC is set up and interrupts enabled. Global interrupts are also enabled, so make sure all other interrupts are correctly configured before running this. The interrupt routine VADC_ISR does the actual vadc measurements.
Definition at line 215 of file vadc_usage.c.
References FIRST_VADC_MEAS, and vadc_scan_complete.
Referenced by main().
00216 { 00217 //disable ADC0-1 digital input buffer. 00218 DIDR0 = 0x03; 00219 vadc_scan_complete = 0; 00220 00221 // Start set up for first channel. 00222 VADMUX = FIRST_VADC_MEAS; 00223 00224 // Clear any pending interrupt 00225 VADCSR = (1<<VADEN) | (1<<VADCCIF); 00226 00227 //Start the first conversion & enable interrupts 00228 VADCSR = (1<<VADEN) | (1<<VADSC) | (1<<VADCCIE); 00229 00230 // Make sure interrupt are enabled. 00231 __enable_interrupt(); 00232 }
| __interrupt void VADC_ISR | ( | void | ) |
Interrupt Service Function to measure VADC values.
Measurements are stored in global array vadc_measurement[]. The ISR scans all inputs and then disables itself. It starts with temperature sensor and normal VADc channels. Cells are measured last to give possiblity to disable cell balancing in relevant devices (HVB/m406). This routine can be simplified for HVA.
Definition at line 245 of file vadc_usage.c.
References BOTTOM_CELL, LAST_VADC_MEAS, TOP_CELL, vadc_measurement, and vadc_scan_complete.
00246 { 00247 uint8_t temp; 00248 00249 // Used for indexing the vadc_measurement variable 00250 static uint8_t vadc_index = 0; 00251 00252 temp = VADMUX; 00253 00254 // Save the result 00255 vadc_measurement[vadc_index] = VADC; 00256 00257 /* Code could be added here to store current with the associated cell 00258 * voltage if doing cell impedance measurements. 00259 */ 00260 00261 temp++; 00262 vadc_index++; 00263 00264 /* Check for disabling of cell balancing could be inserted here or in "if" 00265 * below. Timing must be adjusted according to discharge time constant. 00266 */ 00267 00268 if(temp > LAST_VADC_MEAS){ 00269 // Finished with no cell inputs. Do cell measurements. 00270 temp = BOTTOM_CELL; 00271 } else { 00272 // Finished with all cells also? 00273 if(temp == (TOP_CELL+1)){ 00274 // Flag that we have new samples! 00275 vadc_scan_complete = 1; 00276 00277 /* Possibly re-enable cell balancing here. */ 00278 00279 // Disable this ADC and its Interrupt. 00280 VADCSR = 0; 00281 vadc_index = 0; 00282 return; 00283 } 00284 } 00285 00286 VADMUX = temp; 00287 00288 //Start next conversion now. 00289 VADCSR |= (1<<VADSC); 00290 }
| uint16_t bg_temp |
Global variable for the result of band-gap temperature measurement/calculation.
Definition at line 79 of file vadc_usage.c.
Referenced by CalculateADCResults().
| uint16_t cell_gain[NO_CELLS] |
Gain coefficients for Cells.
Definition at line 67 of file vadc_usage.c.
Referenced by CalculateADCResults(), and InitCoeff().
| int8_t cell_offset[NO_CELLS] |
Offset for cells.
Definition at line 68 of file vadc_usage.c.
Referenced by CalculateADCResults(), and InitCoeff().
| uint16_t cell_v[NO_CELLS] |
Global variable for results of Cell Voltage measurements/calculations.
Definition at line 77 of file vadc_usage.c.
Referenced by CalculateADCResults().
| uint16_t vadc_gain[NO_VADC] |
VADC channel gain.
Definition at line 69 of file vadc_usage.c.
Referenced by CalculateADCResults(), and InitCoeff().
| uint16_t vadc_measurement[NO_VADC_CHANNELS] |
Global variable for VADC samples. Sized to number of VADC channels.
Definition at line 76 of file vadc_usage.c.
Referenced by CalculateADCResults(), and VADC_ISR().
| int8_t vadc_offset[NO_VADC] |
VADC channel offset.
Definition at line 70 of file vadc_usage.c.
Referenced by CalculateADCResults(), and InitCoeff().
| uint8_t vadc_scan_complete |
Flag for signalling VADC sampling complete.
Definition at line 80 of file vadc_usage.c.
Referenced by main(), StartVADCScan(), and VADC_ISR().
| uint16_t vadc_v[NO_VADC] |
Global variable for results of Voltage ADC measurements/calculations.
Definition at line 78 of file vadc_usage.c.
Referenced by CalculateADCResults().
| uint16_t vptat_coeff |
Internal temperature sensor coefficient.
Definition at line 66 of file vadc_usage.c.
Referenced by CalculateADCResults(), and InitCoeff().
1.5.5