Forum: Mikrocontroller und Digitale Elektronik Interrupts konkurrieren


von Andre S. (xolom)


Lesenswert?

Hallo.

Ich habe hier ein kleines Problem mit meinem ATxmega128A1.

Es soll mit einer Frequenz von 250kHz Werte vom ADc eingelesen werden.
Der ADC ist momentan im Freerun modus konfiguriert und der 
Interrupt-mode ist auf "complete" gestelt.

Die ISR des ADCs sieht so aus:
1
ISR(ADCA_CH0_vect) {
2
    PORTF.OUTTGL = PIN1_bm;
3
    if (protectFlag == 0) {
4
        adcAvgVal += val;
5
        adcSamples++;
6
    }
7
}

So weit so gut. Bis hierher funktioniert alles ohne Probleme. Die 250kHz 
wurden mittels Oszi kontrolliert.

Jetzt habe ich einen Timer, welcher mit 40kHz getaktet ist. Dieser Timer 
soll in jeden Taktzyklus das arithmetische Mittel des ADC-Wertes 
berechnen und diesen in einer Variable speichern.

Den Timer prüfe ich manuell in der Main-While-Schleife ab (ich dachte so 
kann ich einen interrupt vermeiden, da ich nur auf das Flag prüfe)
1
if ((TCC0.INTFLAGS & TC0_OVFIF_bm) != 0) {
2
    TCC0.INTFLAGS = TC0_OVFIF_bm;
3
    //PORTF.OUTTGL = PIN1_bm;
4
    protectFlag = 1;
5
    currentVal  = adcAvgVal / adcSamples;
6
    adcSamples  = 0;
7
    adcAvgVal   = 0;
8
    protectFlag = 0;
9
}

Jetzt zum eigentlichen Problem:
Sobald der ADC und der Timer die slebe Interrupt-Priorität haben, kommt 
der ADC-Interrupt nicht mehr an die Reihe. Es ist immer ein entweder 
oder.

von Falk B. (falk)


Lesenswert?

@Andre S. (xolom)

>Es soll mit einer Frequenz von 250kHz Werte vom ADc eingelesen werden.

Ganz schönn schnell!

>Jetzt habe ich einen Timer, welcher mit 40kHz getaktet ist. Dieser Timer
>soll in jeden Taktzyklus das arithmetische Mittel des ADC-Wertes
>berechnen und diesen in einer Variable speichern.

Das machst du besser in deinem 250kHz Interrupt, da ist das besser 
synchronisiert und die beiden ISRs spucken sich nicht gegenseitig in's 
Timing.

>Sobald der ADC und der Timer die slebe Interrupt-Priorität haben, kommt
>der ADC-Interrupt nicht mehr an die Reihe. Es ist immer ein entweder
>oder.

Da ist wohl was falsch konfiguriert.

von Bitflüsterer (Gast)


Lesenswert?

Wie stellst Du fest, das der ADC-Interrupt nicht mehr drankommt?

Warum spielt die Interrupt-Priorität aus Deiner Sicht eine Rolle, wenn 
Du doch keine Interrupt-Routine für den Timer verwendest? Nach Deinem 
Codeschnipsel gibt es nur einen Interrupt.

Warum ist die Frequenz mit welcher der Mittelwert berechnet wird, kein 
Teiler der Abtastfrequenz? Warum wird der Mittelwert nicht als 
Konsequenz (im kausalen Sinn) der Abtastung berechnet sondern unabhängig 
davon?

von Oliver L. (olubritz)


Lesenswert?

Hi Andre,
normalerweise sollten zwei Interrupts gleicher Priorität sich natürlich 
nicht ausschließen, sondern nacheinander abgearbeitet werden wenn sie 
gleichzeitig auftreten sollen =)

Der Hinweis von Bitflüsterer ist gut mit der Interrupt-Service-Routine. 
Wenn du keine hast kann sich dein Programm aufhängen, da der Controller 
nicht weiss wo er "hinspringen" soll. Ich glaube es gibt zwar eine 
"Default"-ISR aber diese muss auch definiert sein, damit sie greift.

Auf welche Priorität setzt du sie denn? Nutzt du die Defines, wie 
ADC_CH_INTLVL_LO_gc? Mir ist es mal passiert, dass ich für das Setzen 
eines Timer Interrupt eine falsche Define verwendet habe und er somit 
einen ganz anderen Wert im Register gesetzt hat. Deswegen die Frage nach 
der Define.

Ansonsten kann man die einzelnen Interrupt-Prioritäten auch sperren. Um 
alle einzuschalten reicht normalerweise die Funktion pmic_init().

Gruß Olli

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.