AVR ADC Interrupt kann nicht ausgelöst werden

Ich verwende ein XPlained-Miniboard von Atmel mit Atmega328PB. Ich versuche, den ADC-Interrupt zu verwenden, kann ihn jedoch nicht auslösen. Hier ist der Code, mit dem ich ein Problem habe:

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

Soweit ich weiß, sollte der Code eine konstante Konvertierung in einen frei laufenden Modus mit der Frequenz von 16 MHz/128 ermöglichen, und jedes Mal, wenn die Konvertierung abgeschlossen ist, sollte der ADC_vect das Umschalten von PIN2 von Port C auslösen. Das Problem ist, dass dies nicht der Fall ist. Ich vermute, dass ich den ADC nicht richtig initialisiere, aber ich kann nicht genau bestimmen, wo das Problem liegt.

BEARBEITEN : Nachdem ich darauf hingewiesen hatte, dass der Adc nicht in einem freilaufenden Modus ausgeführt wurde, habe ich die ADTS-Bits gelöscht. Allerdings konnte ich den Pin immer noch nicht umschalten. Ich denke, hier ist etwas anderes schuld.

Antworten (2)

Du hast geschrieben

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

Und ich denke, es sollte sein

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

Was plausibel erscheint, da der Fehler, auf den Sie gestoßen sind, darin besteht, dass es nie etwas tut.

Das ist völlig richtig, schade, dass ein solcher Fehler keine Warnung auslöst.
@AnthropomorphousDodecahedron Well 1<ADENwird so ausgewertet, als wäre es in einer ifAnweisung enthalten. Ich weiß nicht, welchen Wert ADEN tatsächlich hat, aber wenn er beispielsweise gleich 2 ist, wird daraus 1<ADENdas true, 00000001was dann mit ADCSRA ODER: verknüpft wird. - Es sollte also weder einen Fehler noch eine Warnung erzeugen, es ist ein vollkommen legaler Code.

Siehe Tabelle 24-6 des Datenblatts . Sie setzen die Bits ADTS1 und ADTS0 hoch (lassen ADTS2 auf Null). Dies bedeutet, dass das Triggersignal "Timer/Counter0 Compare Match A" ist. Sie tun nichts, um diesen Timer zu konfigurieren (und der Reset-Status des Timers ist einfach "gestoppt").

Um den freilaufenden Modus zu verwenden, müssen Sie ADTS0, ADTS1, ADTS2 in ADCSRB löschen ( oder ADCSRB einfach auf seinem zurückgesetzten Wert belassen ).

Filo hat Recht. "ADCSRB |= (1 << ADTS1) | (1 << ADTS0); //freilaufender Modus" Hier stellen Sie nicht den freilaufenden Modus ein, wie der Kommentar erwähnt. Für den Freilaufmodus: ADCSRB = ~( (1 << ADTS2) | (1 << ADTS1) | (1 << ADTS0) );
Obwohl die Korrektur richtig ist und sich adc nicht im Freilaufmodus befand, scheint auch etwas anderes schuld zu sein, da der Pin immer noch nicht umgeschaltet wurde, selbst nachdem ich die ADTS-Bits gelöscht hatte.