2
\$\begingroup\$

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.

asked Dec 9, 2018 at 20:46
\$\endgroup\$
0

2 Answers 2

4
+50
\$\begingroup\$

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.

answered Dec 17, 2018 at 17:25
\$\endgroup\$
2
  • \$\begingroup\$ That's absolutely right, too bad that such a mistake doesn't trigger any kind of warning. \$\endgroup\$ Commented Dec 20, 2018 at 7:16
  • \$\begingroup\$ @AnthropomorphousDodecahedron Well 1<ADEN is evaluated as if it was inside a if statement. I don't know what value ADEN actually is, but if it is, say equal to 2, then 1<ADEN becomes true which becomes 00000001 which is then OR:ed with ADCSRA. - So it shouldn't generate an error nor a warning, it is perfectly legal code. \$\endgroup\$ Commented Dec 20, 2018 at 8:12
2
\$\begingroup\$

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).

answered Dec 9, 2018 at 22:26
\$\endgroup\$
2
  • \$\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\$ Commented 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\$ Commented Dec 13, 2018 at 21:07

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.