• 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 }

Generated on Tue Nov 8 2011 16:29:45 for ATMEL by  doxygen 1.7.2