- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# adc.c

Go to the documentation of this file.

    00001 /*This file is prepared for Doxygen automatic documentation generation.*/
    00016
    00017 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
    00018  *
    00019  * Redistribution and use in source and binary forms, with or without
    00020  * modification, are permitted provided that the following conditions are met:
    00021  *
    00022  * 1. Redistributions of source code must retain the above copyright notice,
    00023  * this list of conditions and the following disclaimer.
    00024  *
    00025  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00026  * this list of conditions and the following disclaimer in the documentation
    00027  * and/or other materials provided with the distribution.
    00028  *
    00029  * 3. The name of Atmel may not be used to endorse or promote products derived
    00030  * from this software without specific prior written permission.
    00031  *
    00032  * 4. This software may only be redistributed and used in connection with an Atmel
    00033  * AVR product.
    00034  *
    00035  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
    00036  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00037  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00038  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00039  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00040  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00041  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00042  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00043  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00044  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00045  */
    00046
    00047 #include "config.h"
    00048 #include "structs.h"
    00049 #include "main.h"
    00050
    00051 #ifdef __GNUC__
    00052    #include "lib_mcu/adc/adc.h"
    00053    #include "lib_mcu/adc/adc_drv.h"
    00054 #elif __ICCAVR__
    00055    #include "adc.h"
    00056    #include "adc_drv.h"
    00057 #else
    00058    #error Current COMPILER not supported
    00059 #endif
    00060
    00061 //******************************************************************************
    00062 // Variables
    00063 //******************************************************************************
    00064 // ADC status struct.
    00066 volatile ADC_Status_t ADCS;
    00067
    00068 //******************************************************************************
    00069 // Functions
    00070 //******************************************************************************
    00110 #ifdef __GNUC__
    00111  ISR(ADC_vect)
    00112 #else
    00113 #pragma vector = ADC_vect
    00114 __interrupt void ADC_ISR(void)
    00115 #endif
    00116 {
    00117    static unsigned char avgIndex = 0;
    00118    unsigned char i, Next;
    00119    signed int  temp = 0;
    00120    unsigned long temp_buffer;
    00121
    00122    // Handle the conversion, depending on what channel it is from, then
    00123    // switch to the next channel in the sequence.
    00124    switch (ADCS.MUX){
    00125
    00126       // MUX = 0x09 => ADC0/ADC1 (PF0/PF1) = Vshunt
    00127       case 0x01:
    00128       case 0x05:
    00129          //First differential with no accuracy
    00130          //need second one
    00131          if(ADCS.MUX == 0x01)
    00132          {
    00133             Next=0x05;
    00134          }
    00135          else
    00136          {
    00137
    00138             // If bipolar, from -512 to 0, to 511:
    00139             // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF
    00140             if (ADC > 511) {
    00141                //Negative value (battery charge)
    00142                temp_buffer = (I_SCALE_1 * (1024 -ADC)) / I_SCALE_2;
    00143                ADCS.IBAT = -(signed int)temp_buffer;
    00144
    00145                //for demo current always positive
    00146                ADCS.IBAT = 0;
    00147             }
    00148             else if (ADC > 0){
    00149                //Positive value (battery discharge)
    00150                temp_buffer = (I_SCALE_1 * ADC) / I_SCALE_2;
    00151                  ADCS.IBAT = (signed int)temp_buffer;
    00152             }
    00153             else{
    00154                ADCS.IBAT = 0;
    00155             }
    00156
    00157             // Insert sample of battery current into the averaging-array
    00158             // (overwriting the oldest sample), then recalculate and store the
    00159             // average. This is the last conversion in the sequence, so
    00160             // flag a complete ADC-cycle and restart sequence.
    00161             ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;
    00162             for (i = 0; i < 4 ; i++) {
    00163                temp += ADCS.discIBAT[i];
    00164             }
    00165
    00166             ADCS.avgIBAT = (temp / 4);
    00167
    00168             Next=0x02;
    00169
    00170             //Mux 0x00 for next measurement (case 0x02)
    00171             Clear_adc_mux();
    00172          }
    00173       break;
    00174
    00175       // MUX = 0x00 => ADC0 (PF0) = VBAT
    00176       case 0x02:
    00177          temp_buffer = (VBAT_SCALE_1 * ADC )/VBAT_SCALE_2;
    00178
    00179          ADCS.rawVBAT = (unsigned int)temp_buffer;
    00180             ADCS.rawVBAT = ADCS.rawVBAT;
    00181
    00182             //ADCS.VBAT = ADCS.rawVBAT;
    00183            ADCS.VBAT = (ADCS.VBAT + ADCS.rawVBAT)>>1;
    00184
    00185
    00186 #if(TARGET_BOARD == MEGAU4EK)
    00187          //Only to use the same SW that VARTA batteries
    00188          ADCS.rawNTC = 671;
    00189          ADCS.rawRID = 300;
    00190
    00191          ADCS.Flag = TRUE;
    00192          Next=0x01;
    00193
    00194          //Mux 09 for next measurement (case 0x01)
    00195          Clear_adc_mux();
    00196          Select_adc_channel(0x09);
    00197
    00198 #else
    00199          Next=0x03;
    00200
    00201
    00202          //Mux Ox23 for next measurement (case 0x03)
    00203          Clear_adc_mux();
    00204          Select_adc_channel(0x23);
    00205 #endif
    00206
    00207       break;
    00208
    00209       // MUX = 0x23 => ADC11 (PB4) = NTC
    00210       case 0x03:
    00211 #ifdef TRUSTFIRE
    00212          ADCS.rawNTC = 671;//ADC replaced for TrustFire battery (26°)
    00213 #else
    00214          ADCS.rawNTC = ADC;
    00215 #endif
    00216
    00217          Next=0x04;
    00218
    00219          //Mux 0x24 for next measurement (case 0x04)
    00220          Clear_adc_mux();
    00221          Select_adc_channel(0x24);
    00222       break;
    00223
    00224       // MUX = 0x24 => ADC12 (PB5) = RID
    00225       case 0x04:
    00226 #ifdef TRUSTFIRE
    00227          ADCS.rawRID = 300;//ADC replaced for TrustFire battery (550mA)
    00228 #else
    00229          ADCS.rawRID = ADC;
    00230 #endif
    00231          ADCS.Flag = TRUE;
    00232          Next=0x01;
    00233
    00234          //Mux 09 for next measurement (case 0x01)
    00235          Clear_adc_mux();
    00236          Select_adc_channel(0x09);
    00237       break;
    00238
    00239       default:  // Should not happen. (Invalid MUX-channel)
    00240          Next=0x01;  // Start at the beginning of sequence.
    00241
    00242          //Mux 09 for next measurement (case 0x01)
    00243          Clear_adc_mux();
    00244          Select_adc_channel(0x09);
    00245       break;
    00246    }
    00247
    00248    // Update MUX to next channel in sequence, set a bipolar conversion if
    00249    // this has been flagged.
    00250    ADCS.MUX = Next;
    00251
    00252    // Re-enable the ADC unless a halt has been flagged and a conversion
    00253    // cycle has completed.
    00254    if (!(ADCS.Flag))
    00255    {
    00256       Start_conv();
    00257    }
    00258
    00259 }
    00260
    00261
    00268 void ADC_Wait(void)
    00269 {
    00270    //adc enable
    00271 // Enable_adc();
    00272    ADCS.Flag = FALSE;
    00273
    00274    //start a conversion
    00275    Start_conv();
    00276
    00277    //wait a complete conversion
    00278    do {
    00279    } while (ADCS.Flag == FALSE);
    00280
    00281    //adc enable
    00282 // Enable_adc();
    00283    ADCS.Flag = FALSE;
    00284
    00285    //start a second conversion
    00286    Start_conv();
    00287
    00288    //wait a complete conversion
    00289    do {
    00290    } while (ADCS.Flag == FALSE);
    00291
    00292    //stop ADC (to share CPU time)
    00293 // Disable_adc();
    00294 }
    00295
    00296
    00303 void ADC_Init(void)
    00304 {
    00305    unsigned char i;
    00306
    00307 #ifdef __GNUC__
    00308    Disable_interrupt();
    00309 #else
    00310    __disable_interrupt();
    00311 #endif
    00312
    00313    ADCS.Halt = FALSE; // Enable consecutive runs of ADC.
    00314
    00315    // Configure ADC pins (inputs and disabled pull-ups).
    00316    //PF0 PF1
    00317    DDRF &= ~((1<<DDF1)|(1<<DDF0));
    00318    PORTF &= ~((1<<PORTF1)|(1<<PORTF0));
    00319
    00320    //DIDR0: disable digital input buffer for PF1 and PF0
    00321    //power consumption improvement
    00322    DIDR0 |= ((1<<ADC1D)|(1<<ADC0D));
    00323
    00324 #if(TARGET_BOARD != MEGAU4EK)
    00325    //PB5 PB4
    00326    DDRB &= ~((1<<DDB5)|(1<<DDB4));
    00327    PORTB &= ~((1<<PORTB5)|(1<<PORTB4));
    00328
    00329    //DIDR2: disable digital input buffer for PB5 and PB4
    00330    //power consumption improvement
    00331    DIDR2 |= ((1<<ADC12D)|(1<<ADC11D));
    00332 #endif
    00333
    00334    // Reset the ADC-cycle.
    00335    ADCS.Flag = FALSE;
    00336    ADCS.MUX = 0x01;
    00337
    00338    //Vshunt measurement
    00339    //Select 2.56V as reference + MUX = 0x09
    00340    //Mux 09
    00341    Clear_adc_mux();
    00342    Enable_internal_vref();
    00343    Select_adc_channel(0x09);
    00344
    00345     Enable_adc_high_speed_mode();
    00346
    00347 #if(TARGET_BOARD == MEGAU4EK)
    00348     //Set prescaler to 7 (\128) => 16MHz\128 = 125kHz (max 200kHz)
    00349     Set_adc_prescaler(7);
    00350 #else
    00351     //Set prescaler to 6 (\64) => 8MHz\64 = 125kHz (max 200kHz)
    00352     Set_adc_prescaler(6);
    00353 #endif
    00354
    00355    // Clear averaged battery current and the discrete readings.
    00356    ADCS.avgIBAT = 0;
    00357
    00358    for (i = 0; i < 4; i++) {
    00359       ADCS.discIBAT[i] = 0;
    00360    }
    00361
    00362    // Re-enable the ADC and ISR.
    00363    Enable_adc_it();
    00364    Enable_adc();
    00365
    00366 #ifdef __GNUC__
    00367    Enable_interrupt();
    00368 #else
    00369    __enable_interrupt();
    00370 #endif
    00371
    00372    // Get a complete cycle of data before returning.
    00373    ADC_Wait();
    00374 }