Contains high level functions for initializing the ADC, interrupt handling, and treatment of samples. More...
#include "config.h"#include "structs.h"#include "main.h"
Go to the source code of this file.
Functions | |
| __interrupt void | ADC_ISR (void) |
| Interrupt Service routine for ADC. | |
| void | ADC_Wait (void) |
| Waits for two full cycles of ADC-conversions to occur. | |
| void | ADC_Init (void) |
| Initializes ADC and input pins. | |
Variables | |
| volatile ADC_Status_t | ADCS |
| Holds sampled data and ADC-status. | |
Contains high level functions for initializing the ADC, interrupt handling, and treatment of samples.
The ADC is set to free running mode and uses an internal reference voltage.
Definition in file adc.c.
| __interrupt void ADC_ISR | ( | void | ) |
Interrupt Service routine for ADC.
This ISR stores the sampled values in the ADC status-struct, then updates the ADC MUX to the next channel in the scanning-sequence.
Once the sequence is completed, ADCS.Flag is set and unless ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC is disabled.
If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. VREF = 2.56V
Seq | MUX5 | MUX4:0 | pos I/P | neg I/P | gain | measure | signed
----+------+--------+-----------+----------+-------+-------------+-------
01 | 0 | 01001 | ADC0/PF0 | diff/neg | 10x | Vshunt- | no
| | | ADC1/PF1 | diff/pos | 10x | Vshunt+ | no
| | | | | | |
02 | 0 | 00000 | ADC0/PF0 | n/a | 1x | Vbatt | no
| | | | | | |
03 | 1 | 00011 | ADC11/PB4 | n/a | 1x | NTC | no
| | | | | | |
04 | 1 | 00100 | ADC12/PB5 | n/a | 1x | RID | no
| | | | | | |
05 | 0 | 01001 | ADC0/PF0 | diff/neg | 10x | Vshunt- | no
| | | ADC1/PF1 | diff/pos | 10x | Vshunt+ | no | | | |
| | | | | | |
Definition at line 114 of file adc.c.
References ADCS, Clear_adc_mux, I_SCALE_1, I_SCALE_2, Select_adc_channel, Start_conv, TRUE, VBAT_SCALE_1, and VBAT_SCALE_2.
{
static unsigned char avgIndex = 0;
unsigned char i, Next;
signed int temp = 0;
unsigned long temp_buffer;
// Handle the conversion, depending on what channel it is from, then
// switch to the next channel in the sequence.
switch (ADCS.MUX){
// MUX = 0x09 => ADC0/ADC1 (PF0/PF1) = Vshunt
case 0x01:
case 0x05:
//First differential with no accuracy
//need second one
if(ADCS.MUX == 0x01)
{
Next=0x05;
}
else
{
// If bipolar, from -512 to 0, to 511:
// 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF
if (ADC > 511) {
//Negative value (battery charge)
temp_buffer = (I_SCALE_1 * (1024 -ADC)) / I_SCALE_2;
ADCS.IBAT = -(signed int)temp_buffer;
//for demo current always positive
ADCS.IBAT = 0;
}
else if (ADC > 0){
//Positive value (battery discharge)
temp_buffer = (I_SCALE_1 * ADC) / I_SCALE_2;
ADCS.IBAT = (signed int)temp_buffer;
}
else{
ADCS.IBAT = 0;
}
// Insert sample of battery current into the averaging-array
// (overwriting the oldest sample), then recalculate and store the
// average. This is the last conversion in the sequence, so
// flag a complete ADC-cycle and restart sequence.
ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;
for (i = 0; i < 4 ; i++) {
temp += ADCS.discIBAT[i];
}
ADCS.avgIBAT = (temp / 4);
Next=0x02;
//Mux 0x00 for next measurement (case 0x02)
Clear_adc_mux();
}
break;
// MUX = 0x00 => ADC0 (PF0) = VBAT
case 0x02:
temp_buffer = (VBAT_SCALE_1 * ADC )/VBAT_SCALE_2;
ADCS.rawVBAT = (unsigned int)temp_buffer;
ADCS.rawVBAT = ADCS.rawVBAT;
//ADCS.VBAT = ADCS.rawVBAT;
ADCS.VBAT = (ADCS.VBAT + ADCS.rawVBAT)>>1;
#if(TARGET_BOARD == MEGAU4EK)
//Only to use the same SW that VARTA batteries
ADCS.rawNTC = 671;
ADCS.rawRID = 300;
ADCS.Flag = TRUE;
Next=0x01;
//Mux 09 for next measurement (case 0x01)
Clear_adc_mux();
Select_adc_channel(0x09);
#else
Next=0x03;
//Mux Ox23 for next measurement (case 0x03)
Clear_adc_mux();
Select_adc_channel(0x23);
#endif
break;
// MUX = 0x23 => ADC11 (PB4) = NTC
case 0x03:
#ifdef TRUSTFIRE
ADCS.rawNTC = 671;//ADC replaced for TrustFire battery (26°)
#else
ADCS.rawNTC = ADC;
#endif
Next=0x04;
//Mux 0x24 for next measurement (case 0x04)
Clear_adc_mux();
Select_adc_channel(0x24);
break;
// MUX = 0x24 => ADC12 (PB5) = RID
case 0x04:
#ifdef TRUSTFIRE
ADCS.rawRID = 300;//ADC replaced for TrustFire battery (550mA)
#else
ADCS.rawRID = ADC;
#endif
ADCS.Flag = TRUE;
Next=0x01;
//Mux 09 for next measurement (case 0x01)
Clear_adc_mux();
Select_adc_channel(0x09);
break;
default: // Should not happen. (Invalid MUX-channel)
Next=0x01; // Start at the beginning of sequence.
//Mux 09 for next measurement (case 0x01)
Clear_adc_mux();
Select_adc_channel(0x09);
break;
}
// Update MUX to next channel in sequence, set a bipolar conversion if
// this has been flagged.
ADCS.MUX = Next;
// Re-enable the ADC unless a halt has been flagged and a conversion
// cycle has completed.
if (!(ADCS.Flag))
{
Start_conv();
}
}
| void ADC_Wait | ( | void | ) |
Waits for two full cycles of ADC-conversions to occur.
This function clears the cycle complete-flag, then waits for it to be set again. This is then repeated once before the function exits.
Definition at line 268 of file adc.c.
References ADCS, FALSE, and Start_conv.
Referenced by ADC_Init().
{
//adc enable
// Enable_adc();
ADCS.Flag = FALSE;
//start a conversion
Start_conv();
//wait a complete conversion
do {
} while (ADCS.Flag == FALSE);
//adc enable
// Enable_adc();
ADCS.Flag = FALSE;
//start a second conversion
Start_conv();
//wait a complete conversion
do {
} while (ADCS.Flag == FALSE);
//stop ADC (to share CPU time)
// Disable_adc();
}

| void ADC_Init | ( | void | ) |
Initializes ADC and input pins.
This function initializes the ADC to free running mode,.
Definition at line 303 of file adc.c.
References ADC_Wait(), ADCS, Clear_adc_mux, Enable_adc, Enable_adc_high_speed_mode, Enable_adc_it, Enable_internal_vref, FALSE, Select_adc_channel, and Set_adc_prescaler.
{
unsigned char i;
#ifdef __GNUC__
Disable_interrupt();
#else
__disable_interrupt();
#endif
ADCS.Halt = FALSE; // Enable consecutive runs of ADC.
// Configure ADC pins (inputs and disabled pull-ups).
//PF0 PF1
DDRF &= ~((1<<DDF1)|(1<<DDF0));
PORTF &= ~((1<<PORTF1)|(1<<PORTF0));
//DIDR0: disable digital input buffer for PF1 and PF0
//power consumption improvement
DIDR0 |= ((1<<ADC1D)|(1<<ADC0D));
#if(TARGET_BOARD != MEGAU4EK)
//PB5 PB4
DDRB &= ~((1<<DDB5)|(1<<DDB4));
PORTB &= ~((1<<PORTB5)|(1<<PORTB4));
//DIDR2: disable digital input buffer for PB5 and PB4
//power consumption improvement
DIDR2 |= ((1<<ADC12D)|(1<<ADC11D));
#endif
// Reset the ADC-cycle.
ADCS.Flag = FALSE;
ADCS.MUX = 0x01;
//Vshunt measurement
//Select 2.56V as reference + MUX = 0x09
//Mux 09
Clear_adc_mux();
Enable_internal_vref();
Select_adc_channel(0x09);
Enable_adc_high_speed_mode();
#if(TARGET_BOARD == MEGAU4EK)
//Set prescaler to 7 (\128) => 16MHz\128 = 125kHz (max 200kHz)
Set_adc_prescaler(7);
#else
//Set prescaler to 6 (\64) => 8MHz\64 = 125kHz (max 200kHz)
Set_adc_prescaler(6);
#endif
// Clear averaged battery current and the discrete readings.
ADCS.avgIBAT = 0;
for (i = 0; i < 4; i++) {
ADCS.discIBAT[i] = 0;
}
// Re-enable the ADC and ISR.
Enable_adc_it();
Enable_adc();
#ifdef __GNUC__
Enable_interrupt();
#else
__enable_interrupt();
#endif
// Get a complete cycle of data before returning.
ADC_Wait();
}

| volatile ADC_Status_t ADCS |
Holds sampled data and ADC-status.
Definition at line 66 of file adc.c.
Referenced by ADC_Init(), ADC_ISR(), and ADC_Wait().
1.7.2