Hello all,
I come from a background of ST/Microchip programming, and in order to teach myself using Atmel micros, I'm writing myself a small software library.
At the moment I'm having trouble with getting ADC reads with interrupts to work.
The code I have so far is here: https://github.com/jamesfowkes/Code-Library/blob/master/AVR/lib_adc.c.
I'm using it in the following manner with an ATTINY84A
In main():
ADC_Enable(true); // Should set ADEN in ADCSRA ADC_EnableInterrupts(true); // Should set ADIE in ADCSRA ADC_SelectPrescaler(LIB_ADC_PRESCALER_DIV64); // Sets /64 prescaler (125kHz ADC clock with 8MHz fCPU) ADC_SelectReference(LIB_ADC_REF_VCC);
And then in a timer interrupt callback (which I know works correctly):
uint16_t result; result = ADC_GetReading(LIB_ADC_CH_0); /* post result to serial port... */
The relevant functions of code in the library is:
uint16_t ADC_GetReading(LIB_ADC_CHANNEL_ENUM eChannel) { validReading = false; SetChannel(eChannel); ADCSRA |= (1 << ADSC); // Start conversion while (!validReading){ asm("nop"); } return lastReading; } ISR(ADC_vect) { uint16_t result = 0; result = ADCL; result |= ADCH << 8; lastReading = result; validReading = true; }
validReading is declared as static volatile bool.
lastReading is declared as static volatile uint16_t.
As far as I'm aware, the ADC_GetReading function should run until the ADC completes, the validReading flag is set, and the result can be returned. However, as far as I can tell the ISR is never called (I tried to turn an LED on inside it and it stayed off).
If I disable the ADC interrupt and do the following instead:
uint16_t ADC_GetReading(LIB_ADC_CHANNEL_ENUM eChannel) { validReading = false; SetChannel(eChannel); ADCSRA |= (1 << ADSC); // Start conversion while (ADCSRA & (1 << ADSC)){ asm("nop"); } uint16_t result = ADCL; result |= ADCH << 8; return result; }
This works correctly.
However, my intention is to use an interrupt+callback architecture to remove the while loop entirely. But I want to get the interrupt working first.
Can anyone suggest where I might be going wrong? I've scoured a lot of websites/tutorials and I'm stumped.