I am trying to set up continuous conversion on ATmega328P ADC. However the ADC interrupt is not firing. What mistake am I making here?
void adc_init(void)
{
skip_sample = true;
sample_id = 0;
ADMUX = 0;
ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS1) | _BV(ADPS0);
ADCSRB = 0;
DIDR0 = _BV(ADC0D);
ADCSRA |= _BV(ADSC) | _BV(ADIF);
}
Have you missed to include interrupt subroutine?
Interrupts still globally turned off? I.e., have you forgotten sei()?
_BV(ADPS1) | _BV(ADPS0);
Implies the system clock is only 1.6Mhz.
Should ADIF be ADIE.
Interrupts still globally turned off? I.e., have you forgotten sei()?
Interrupts on. Other interrupts are firing normally.
Have you missed to include interrupt subroutine?
That is where a portion of application code resides. Those are left out intentionally.
_BV(ADPS1) | _BV(ADPS0);
Implies the system clock is only 1.6Mhz.
Should ADIF be ADIE.
I have a 8MHz clock. Changed the clock divider to ck/64 (125kHz at 8MHz system clock) but still no luck.
I have set both ADIF and ADIE, set ADIF to clear it, set ADIE to enable the interrupt.
Have you missed to include interrupt subroutine?
That is where a portion of application code resides. Those are left out intentionally.
How we supposed to know your spelling is correct?
ISR(ADC_vect) {
}
And what makes you think it's not fired?
Have you missed to include interrupt subroutine?
That is where a portion of application code resides. Those are left out intentionally.
How we supposed to know your spelling is correct?
ISR(ADC_vect) {
}
And what makes you think it's not fired?
I have no compiler warning or error with -Wall, which makes me believe that my spelling is correct. Missed typings on function prototype will lead to a compiler warning.
I have a breakpoint on this function (I am debugging through an Atmel ICE) but the it is not hit.
Interrupts still globally turned off? I.e., have you forgotten sei()?
Sigh, been there. I once spent the better part of an entire day banging my head against the wall trying to figure out what was going on before I realised.
Try this:
ISR(ADC_vect)
{
// turn on LED here. Never turn it off, so you can see if this ever fires
}
main()
{
// turn on LED here to test it works
delay_ms(500);
// turn off LED here
delay_ms(500);
ADMUX = 0; // should be irrelevant to this problem
// Magical code lines copypasted from some of my old random project, which works, runs ADC (ATMega640) in continuous mode and gives interrupts:
ADCSRB = 0b00000000; // free running mode
ADCSRA = 0b11101110; // prescaler = 64: auto trigger.
// and...
sei();
while(1);
}
If this works, just compare what's different between this and yours.
We assume you haven't powered down the ADC via the PRR0 register.
Besides... You have set the auto trigger bits to free running (000). From the datasheet:
If ADATE in ADCSRA is written to one, the value of these bits selects which source will trigger an ADC
conversion. If ADATE is cleared, the ADTS[2:0] settings will have no effect. A conversion will be triggered
by the rising edge of the selected Interrupt Flag. Note that switching from a trigger source that is cleared
to a trigger source that is set, will generate a positive edge on the trigger signal. If ADEN in ADCSRA is
set, this will start a conversion. Switching to Free Running mode (ADTS[2:0]=0) will not cause a trigger
event, even if the ADC Interrupt Flag is set.
Table 29-6 ADC Auto Trigger Source Selection
ADTS[2:0] Trigger Source
000 Free Running mode
001 Analog Comparator
010 External Interrupt Request 0
011 Timer/Counter0 Compare Match A
100 Timer/Counter0 Overflow
101 Timer/Counter1 Compare Match B
110 Timer/Counter1 Overflow
111 Timer/Counter1 Capture Event
Hint: Seems to imply that no trigger even will occur in free running mode... No trigger event means a new conversion won't be initiated.
cheers,
george.
Try this:
ISR(ADC_vect)
{
// turn on LED here. Never turn it off, so you can see if this ever fires
}
main()
{
// turn on LED here to test it works
delay_ms(500);
// turn off LED here
delay_ms(500);
ADMUX = 0; // should be irrelevant to this problem
// Magical code lines copypasted from some of my old random project, which works, runs ADC (ATMega640) in continuous mode and gives interrupts:
ADCSRB = 0b00000000; // free running mode
ADCSRA = 0b11101110; // prescaler = 64: auto trigger.
// and...
sei();
while(1);
}
If this works, just compare what's different between this and yours.
Not working...
We assume you haven't powered down the ADC via the PRR0 register.
Besides... You have set the auto trigger bits to free running (000). From the datasheet:
If ADATE in ADCSRA is written to one, the value of these bits selects which source will trigger an ADC
conversion. If ADATE is cleared, the ADTS[2:0] settings will have no effect. A conversion will be triggered
by the rising edge of the selected Interrupt Flag. Note that switching from a trigger source that is cleared
to a trigger source that is set, will generate a positive edge on the trigger signal. If ADEN in ADCSRA is
set, this will start a conversion. Switching to Free Running mode (ADTS[2:0]=0) will not cause a trigger
event, even if the ADC Interrupt Flag is set.
Table 29-6 ADC Auto Trigger Source Selection
ADTS[2:0] Trigger Source
000 Free Running mode
001 Analog Comparator
010 External Interrupt Request 0
011 Timer/Counter0 Compare Match A
100 Timer/Counter0 Overflow
101 Timer/Counter1 Compare Match B
110 Timer/Counter1 Overflow
111 Timer/Counter1 Capture Event
Hint: Seems to imply that no trigger even will occur in free running mode... No trigger event means a new conversion won't be initiated.
cheers,
george.
I have tried to sort-of emulate continuous mode by not setting ADATE in adc_init, but set ADSC in the end of the ADC interrupt. No luck either, there isn't even an initial conversion.
Look at the ADC flag register, and the conversion result register - are the flags/value updating? What do the flags say? This way you can rule out either one:
1) ADC not enabled at all, or not triggering
2) ADC converting, but interrupt not firing
If case 2, can you set a breakpoint in the interrupt vector table - or at least take a look at the binary? That would verify there is no issue in the jump table generation. (If I remember the AVR architecture correctly.)
Have you tried single shot first? It would narrow down possibilities.
For example, try this oneliner if you like to try random things by magic number copypasting
:
// ADCSRB = 0 as reset value
sei();
ADCSRA = 0b11001110;