No se puede activar la interrupción AVR ADC

Estoy usando una mini placa XPlained de Atmel con Atmega328PB. Estoy tratando de usar la interrupción ADC, sin embargo, no puedo hacer que se dispare. Aquí está el código con el que tengo un problema:

#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) 
    {
    }
}

Según tengo entendido, el código debería permitir una conversión constante en un modo de ejecución libre con una frecuencia de 16 MHz/128, y cada vez que se complete la conversión, el ADC_vect debería activarse alternando el PIN2 del Puerto C. El problema es que no lo hace. Supongo que no estoy inicializando el ADC correctamente, sin embargo, no puedo señalar dónde está el problema.

EDITAR : después de señalar que el adc no se estaba ejecutando en un modo de ejecución libre, borré los bits ADTS. Sin embargo, todavía no podía cambiar el pin. Creo que algo más está fallando aquí.

Respuestas (2)

has escrito

ADCSRA |= (1<ADEN); //adc enable

Y creo que debería ser

ADCSRA |= (1<<ADEN); //adc enable

Lo que parece plausible ya que el error con el que te has encontrado es que nunca hace nada.

Eso es absolutamente correcto, lástima que tal error no active ningún tipo de advertencia.
@AnthropomorphousDodecahedron Well 1<ADENse evalúa como si estuviera dentro de una ifdeclaración. No sé qué valor es ADEN en realidad, pero si lo es, digamos igual a 2, entonces 1<ADENse convierte trueen lo que se convierte 00000001en OR: ed con ADCSRA. - Entonces no debería generar un error ni una advertencia, es un código perfectamente legal.

Consulte la tabla 24-6 de la hoja de datos . Está configurando los bits ADTS1 y ADTS0 en alto (dejando ADTS2 en cero). Significa que la señal de disparo es "Timer/Counter0 Compare Match A". No está haciendo nada para configurar ese temporizador (y el estado de reinicio del temporizador simplemente está "detenido").

Para usar el modo de ejecución libre, debe borrar ADTS0, ADTS1, ADTS2 en ADCSRB ( o simplemente dejar ADCSRB solo en su valor de reinicio ).

Filo tiene razón. "ADCSRB |= (1 << ADTS1) | (1 << ADTS0); //modo de ejecución libre" aquí no establece el modo de ejecución libre como se menciona en el comentario. Para el modo de ejecución libre: ADCSRB = ~( (1 << ADTS2) | (1 << ADTS1) | (1 << ADTS0) );
Si bien la corrección es correcta, y adc no estaba en modo de ejecución libre, parece que también había algo más que fallaba, ya que el pin aún no se alternaba, incluso después de borrar los bits de ADTS.