ADC.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00034 #include <ioavr.h>
00035 #include <inavr.h>
00036 
00037 #include "structs.h"
00038 
00039 #include "main.h"
00040 #include "ADC.h"
00041 
00042 
00043 //******************************************************************************
00044 // Variables
00045 //******************************************************************************
00046 // ADC status struct.
00048 ADC_Status_t ADCS;
00049 
00050 
00072 // Maximum battery voltage (affects scaling of samples).
00073 __eeprom unsigned char VBAT_RANGE = 1;
00074 
00075 
00076 //******************************************************************************
00077 // Functions
00078 //******************************************************************************
00113 #pragma vector=ADC_vect
00114 __interrupt void ADC_ISR(void)
00115 {
00116         static unsigned char avgIndex = 0;
00117         unsigned char i, Next, Signed;
00118         signed int  temp = 0;
00119         
00120         Signed = FALSE;  // Presume next conversion is unipolar.
00121         ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all
00122           // conversions take at least 25 ADCCLK. (It is restarted later)
00123         
00124         // Handle the conversion, depending on what channel it is from, then
00125         // switch to the next channel in the sequence.
00126         switch (ADCS.MUX){
00127                 // MUX = 0b000001 => ADC1 (PA1) = NTC
00128                 case 0x01:
00129                         ADCS.rawNTC = ADC;
00130                         Next=0x02;
00131                 break;
00132 
00133                 
00134                 // MUX = 0b000010 => ADC2 (PA2) = RID
00135                 case 0x02:
00136                         ADCS.rawRID = ADC;
00137                         Next=0x03;
00138                 break;
00139 
00140                 
00141                 // MUX = 0b000011 => ADC3 (PA4) = VIN-
00142                 case 0x03:
00143                         // Supply voltage is always divided by 16.
00144                         ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.
00145                         
00146                         // Is mains failing?
00147                         if (ADCS.VIN < VIN_MIN) {
00148                                 ADCS.Mains = FALSE;
00149                         } else {
00150                                 ADCS.Mains = TRUE;
00151                         }
00152                         
00153                         Next=0x05;
00154                 break;
00155 
00156                 
00157                 // MUX = 0b000101 => ADC5 (PA6) = VBAT-
00158                 case 0x05:
00159                         ADCS.rawVBAT = ADC;
00160                         
00161                         // Scale voltage according to jumper setting.
00162                         ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.
00163                         Next=0x17;
00164 //                      Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!
00165                 break;
00166 
00167 
00168                 case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT
00169                         // If bipolar, from -512 to 0, to 511:
00170                         // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF
00171                 
00172                         // Scale sample according to jumper setting, handle negative numbers.
00173                         if (ADC > 511) {
00174                                 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,
00175                                              (1024 - (ADC-ADCS.ADC5_G20_OS)));
00176                         } else if (ADC > 0) {
00177                                 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));
00178                         } else {
00179                                 ADCS.IBAT = 0;
00180                         }
00181 
00182                         // Insert sample of battery current into the averaging-array
00183                         // (overwriting the oldest sample), then recalculate and store the
00184                         // average. This is the last conversion in the sequence, so
00185                         // flag a complete ADC-cycle and restart sequence.
00186                         ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;
00187                         for (i = 0; i < 4 ; i++) {
00188                                 temp += ADCS.discIBAT[i];
00189                         }
00190                         
00191                         ADCS.avgIBAT = (temp / 4);
00192                         
00193                         ADCS.Flag = TRUE;
00194                         Next=0x01;
00195                         Signed = FALSE;  // This is the only bipolar conversion.
00196                 break;
00197 
00198                 
00199                 default:  // Should not happen. (Invalid MUX-channel)
00200                         Next=0x01;  // Start at the beginning of sequence.
00201                 break;
00202         }
00203         
00204         // Update MUX to next channel in sequence, set a bipolar conversion if
00205         // this has been flagged.
00206         ADCS.MUX = Next;                    
00207         ADMUX = (1<<REFS0) + ADCS.MUX;      
00208 
00209         if (Signed)     {
00210           ADCSRB |= (1<<BIN);               
00211         } else {
00212           ADCSRB &= ~(1<<BIN);              
00213         }
00214 
00215         // Re-enable the ADC unless a halt has been flagged and a conversion
00216         // cycle has completed.
00217         if (!((ADCS.Halt) && (ADCS.Flag))) {
00218           ADCSRA |= (1<<ADEN)|(1<<ADSC);    
00219         }
00220 }
00221 
00222 
00246 unsigned int ScaleU(unsigned char setting, unsigned int data)
00247 {
00248         // Temporary variable needed.
00249         unsigned int scaled = 0;
00250 
00251         // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16
00252         if (setting == 3)       {
00253                 scaled = 29 * data;
00254                 scaled += (data >> 2);
00255                 scaled += (data >> 4);
00256         } else {
00257                 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16
00258                 scaled = 39 * data;
00259                 scaled += (data >> 4);
00260                 
00261                 if (setting <3) {
00262                         // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8
00263                         //                1: mV/LSB = 9.766 = 39.06 / 4
00264                         //                2: mV/LSB = 19.53 = 39.06 / 2
00265                         scaled = (scaled >> (3-setting));
00266                 }
00267         }
00268 
00269         return(scaled);
00270 }
00271 
00272 
00297 unsigned int ScaleI(unsigned char setting, unsigned int data)
00298 {
00299         // Temporary variable needed.
00300         unsigned int  scaled = 0;
00301         
00302         // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128
00303         if (setting == 3) {
00304                 scaled = 21 * data;
00305                 scaled -= (data >> 4);
00306                 scaled += (data >> 7);
00307         }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32
00308                 scaled = 28 * data;
00309                 scaled -= (data >> 3);
00310                 scaled += (data >> 5);
00311                 
00312                 if (setting <3) {
00313                         // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8
00314                         //                1: mA/LSB = 6.978mA = 27.909 / 4
00315                         //                2: mA/LSB = 13.955mA = 27.909 / 2
00316                         scaled = (scaled >> (3-setting));
00317                 }
00318         }
00319         
00320         return(scaled);
00321 }
00322 
00323 
00330 void ADC_Wait(void)
00331 {
00332         // Clear ADC flag and wait for cycle to complete.
00333         ADCS.Flag = FALSE;              
00334         do {
00335         } while (ADCS.Flag == FALSE);      
00336         
00337         // Repeat, so we are sure the data beong to the same cycle.
00338         ADCS.Flag = FALSE;              
00339         do {
00340         } while (ADCS.Flag == FALSE);      
00341 }
00342 
00343 
00369 void ADC_Init(void)
00370 {
00371         unsigned char i;
00372 
00373         __disable_interrupt();
00374 
00375         ADCS.Halt = FALSE; // Enable consecutive runs of ADC.
00376 
00377         // Configure ADC pins (inputs and disabled pull-ups).
00378         DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
00379         PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
00380 
00381         // Set ADC3 as reference, and MUX to measure the same pin.
00382         ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);
00383         
00384         ADCSRB = 0;
00385 
00386         // Start conversion, no interrupt (disable ADC-ISR).
00387         ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; 
00388 
00389         do { // Wait for conversion to finish.
00390         } while (!(ADCSRA & (1<<ADIF)));
00391 
00392         ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.
00393 
00394         ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.
00395 
00396         ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x
00397         
00398         // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.
00399         ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; 
00400 
00401         do { // Wait for conversion to finish.
00402         } while (!(ADCSRA & (1<<ADIF)));
00403 
00404         ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.
00405 
00406         ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.
00407 
00408         // Reset the ADC-cycle.
00409         ADCS.Flag = FALSE;      
00410         ADCS.MUX = 0x01;                    
00411         ADMUX = (1<<REFS0) | ADCS.MUX;      
00412 
00413         // Clear averaged battery current and the discrete readings.
00414         ADCS.avgIBAT = 0;
00415         
00416         for (i = 0; i < 4; i++) {
00417                 ADCS.discIBAT[i] = 0;             
00418         }
00419         
00420         // Re-enable the ADC and ISR.
00421         ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;
00422         
00423         __enable_interrupt();
00424 
00425         // Get a complete cycle of data before returning.
00426         ADC_Wait();
00427 }

Generated on Tue Sep 4 19:17:55 2007 for AVR463 Charging NiMH Batteries with ATAVRBC100 by  doxygen 1.5.2