I was wondering if somebody could shed some light on a problem that I'm having: I'd like to sample with the ADC in an xmega32a4u with one frequency, and report the results with another. But I'd also like to average a window of ADC measurements. This code does not work:
Code:
... defines, includes, etc.
// Globals
volatile int ADCvalue; // record ADC result
int window[ WINDOW_SIZE ]; // the smoothing window
int main( void )
{
... set ups
// Set up and configure PORTE Timer/Counter
TCE0.CTRLA = TC_CLKSEL_DIV64_gc; // divide clock by 64 = 500 kHz
TCE0.PER = 12500; // set clock period to 12500 ( 32 MHz / ( 2 * 64 * 12500 ) = approx 20 Hz for 2 frames )
TCE0.INTCTRLA = TC_OVFINTLVL_LO_gc; // set low level interrupt on overflow
TCE0.CNT = 0; // zero clock
PMIC.CTRL = PMIC_LOLVLEN_bm; // enable low level interrupts
sei(); // enable interrupts
while( 1 )
{
ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0
while( !( ADCA.CH0.CTRL & ADC_CH_START_bm ) ); // wait until it completes
ADCvalue = ADCA.CH0RES;
// Simulate a stack reverse push for reading the ADC value into the window
for ( uint8_t i = 0; i < WINDOW_SIZE - 1; i++ )
window[ i ] = window[ i + 1 ];
window[ WINDOW_SIZE - 1 ] = ADCvalue;
...
_delay_ms( DELAY_TIME );
};
return 0;
};
// LCD controller routine
void LCD_update( void )
{
... display code
}
// Interrupt routine to display on LCD
ISR( TCE0_OVF_vect )
{
LCD_update();
}
As it loads one ADCvalue into one window position only. This code, however, does work:
Code:
... defines, includes, etc.
// Globals
volatile int ADCvalue; // record ADC result
int window[ WINDOW_SIZE ]; // the smoothing window
int main( void )
{
... set ups
// Set up and configure PORTE Timer/Counter
TCE0.CTRLA = TC_CLKSEL_DIV64_gc; // divide clock by 64 = 500 kHz
TCE0.PER = 12500; // set clock period to 12500 ( 32 MHz / ( 2 * 64 * 12500 ) = approx 20 Hz for 2 frames )
TCE0.INTCTRLA = TC_OVFINTLVL_LO_gc; // set low level interrupt on overflow
TCE0.CNT = 0; // zero clock
PMIC.CTRL = PMIC_LOLVLEN_bm; // enable low level interrupts
sei(); // enable interrupts
while( 1 )
{
_delay_ms( DELAY_TIME );
};
return 0;
};
// LCD controller routine
void LCD_update( void )
{
... display code
}
// Interrupt routine to display on LCD
ISR( TCE0_OVF_vect )
{
ADCA.CH0.CTRL |= ADC_CH_START_bm; // start conversion on channel 0
while( !( ADCA.CH0.CTRL & ADC_CH_START_bm ) ); // wait until it completes
ADCvalue = ADCA.CH0RES;
// Simulate a stack reverse push for reading the ADC value into the window
for ( uint8_t i = 0; i < WINDOW_SIZE - 1; i++ )
window[ i ] = window[ i + 1 ];
window[ WINDOW_SIZE - 1 ] = ADCvalue;
LCD_update();
}
But then the ADC samples at an undesired frequency. Any ideas as to why the first doesn't load the entire window (shouldn't it return after the interrupt to the previous position,) and/or how to get the desired behavior?
Many TIA,
Craig |