I am using an Atmel's XPlained mini board with Atmega328PB. I am trying to use ADC interrupt, however I can't get it to fire. Here's the code that I have a problem with:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(ADC_vect){
PORTC ^= (1<<PINC2);
}
int main(void)
{
DDRC |= (1<<PINC2); //pin 2 as output
DDRC &= ~(1<<PINC3); //adc pin as input
sei();
ADMUX |= (1<<REFS0); //reference voltage VCC
ADMUX |= (1<<MUX0);
ADMUX |= (1<<MUX1);// channel 3
ADCSRA |= (1<<ADPS2);//
ADCSRA |= (1<<ADPS1);//
ADCSRA |= (1<<ADPS0);//prescaler to 128
ADCSRA |= (1<<ADATE);//auto trigger enable
ADCSRA |= (1<<ADIE); //adc interrupt enable
ADCSRA |= (1<ADEN); //adc enable
ADCSRA |= (1<< ADSC); //start conversion
while (1)
{
}
}
As far as I understand the code should enable a constant conversion in a free running mode with the frequency of 16MHz/128, and each time the conversion is completed the ADC_vect should fire toggling PIN2 of Port C. The problem is it doesn't. I am guessing I am not initializing the ADC correctly, however I can not pin point were the problem is.
EDIT: After pointing out that the adc was not being run in a free running mode I cleared the ADTS bits. However I still couldn't toggle the pin. I think something else is at fault here.
2 Answers 2
You've written
ADCSRA |= (1<ADEN); //adc enable
And I think it should be
ADCSRA |= (1<<ADEN); //adc enable
Which seems plausible since the error you've come across is that it never does anything.
-
\$\begingroup\$ That's absolutely right, too bad that such a mistake doesn't trigger any kind of warning. \$\endgroup\$Anthropomorphous Dodecahedron– Anthropomorphous Dodecahedron2018年12月20日 07:16:17 +00:00Commented Dec 20, 2018 at 7:16
-
\$\begingroup\$ @AnthropomorphousDodecahedron Well
1<ADEN
is evaluated as if it was inside aif
statement. I don't know what value ADEN actually is, but if it is, say equal to 2, then1<ADEN
becomestrue
which becomes00000001
which is then OR:ed with ADCSRA. - So it shouldn't generate an error nor a warning, it is perfectly legal code. \$\endgroup\$Harry Svensson– Harry Svensson2018年12月20日 08:12:40 +00:00Commented Dec 20, 2018 at 8:12
See table 24-6 of the datasheet. You are setting bits ADTS1 and ADTS0 high (leaving ADTS2 as zero). It means that the trigger signal is "Timer/Counter0 Compare Match A". You are not doing anything to configure that timer (and the reset state of the timer is simply "stopped").
To use the free running mode you have to clear ADTS0, ADTS1, ADTS2 in ADCSRB (or just leave ADCSRB alone at its reset value).
-
\$\begingroup\$ Filo is right. "ADCSRB |= (1 << ADTS1) | (1 << ADTS0); //free running mode" here you do not set the free runing mode as the comment mention. For free runing mode: ADCSRB = ~( (1 << ADTS2) | (1 << ADTS1) | (1 << ADTS0) ); \$\endgroup\$pantarhei– pantarhei2018年12月09日 22:48:38 +00:00Commented Dec 9, 2018 at 22:48
-
\$\begingroup\$ While the correction is right, and adc was not in free running mode it seems something else was also at fault, since the pin was still not being toggled, even after I cleared the ADTS bits. \$\endgroup\$Anthropomorphous Dodecahedron– Anthropomorphous Dodecahedron2018年12月13日 21:07:40 +00:00Commented Dec 13, 2018 at 21:07