Forum: Mikrocontroller und Digitale Elektronik atmega16 interrupt priorität emulieren


von Andreas R. (rebirama)


Lesenswert?

Hallo,

Ich möchte auf einem mega16 verschiedene Interruptprioritäten 
realisieren.

Das Projekt ist ein Leistungsmessgerät für Netzgeräte ("Stromzähler" + 
Extras). Strom und Spannung wird mit 5Khz gemessen, multipliziert und 
integriert...

Vorhandene ISRs:

TIMER1_COMPA_vect:
400Hz
darf unterbrochen werden, deswegen "sei();" am Anfang der Routine
(7-segment display, Auswertungen, Taster entprellen etc.)

TIMER0_COMP_vect:
5Khz
Triggert die Erste von zwei AD-Wandlungen (Spannung).
ADC-Ergebnisse der letzten Messugen multiplizieren und integrieren

ADC_vect:
Holt die ADC-Ergebnisse aus den Registern und triggert die 2te der zwei 
AD-Wandlungen (Strom).
Was ich erreichen möchte: Dass die Timer0-isr vom der ADC-isr 
unterbrochen werden kann, um die 2te Messung so früh wie möglich 
auszulösen.

Als Umsetzung ist das geplant:
1
ISR(TIMER0_COMP_vect)
2
{
3
    uint16_t Current,Voltage;
4
    //Spannungsmessung Starten
5
    ADMUX=3;//Wählen von Channel 3
6
    ADSCRA=0b11001110;//ADC on, ADC start , interrupt enabled, 250KHz ADC-Clock
7
8
    //Alte Ergebnisse abholen
9
    Voltage=strADCControl.u16Voltage;
10
    Current=strADCControl.u16Current;
11
    
12
    TIMSK&=~(1<<OCIE1A);//Deaktiviere den niederprioren Interrupt
13
    sei();//Lasse den höherprioren Interrupt (ADC) zu
14
    
15
    ...
16
    Alte Ergebnisse werden hier multipliziert und integriert
17
    ...
18
19
20
    cli();
21
    TIMSK|=(1<<OCIE1A);//Aktivieren den niederprioren Interrupt wieder

Wird das so funktionieren?
Der Punkt, bei dem ich mir nicht sicher bin: Wenn die Interrupt Flag von 
Timer 1 gesetzt wird, während OCIE1A deaktiviert ist, wird die ISR genau 
nach Verlassen der ISR(TIMER0_COMP_vect) ausgeführt, oder?

Grüße

von Falk B. (falk)


Lesenswert?

@Andreas R. (rebirama)

>Ich möchte auf einem mega16 verschiedene Interruptprioritäten
>realisieren.

Das braucht man nur ganz selten.

>Das Projekt ist ein Leistungsmessgerät für Netzgeräte ("Stromzähler" +
>Extras). Strom und Spannung wird mit 5Khz gemessen, multipliziert und
>integriert...

Ja und? Klingt für mich nicht sonderlich komplex.

>TIMER0_COMP_vect:
>5Khz
>Triggert die Erste von zwei AD-Wandlungen (Spannung).
>ADC-Ergebnisse der letzten Messugen multiplizieren und integrieren

>ADC_vect:
>Holt die ADC-Ergebnisse aus den Registern und triggert die 2te der zwei
>AD-Wandlungen (Strom).

>Was ich erreichen möchte: Dass die Timer0-isr vom der ADC-isr
>unterbrochen werden kann, um die 2te Messung so früh wie möglich
>auszulösen.

Würde ich nicht so machen. Pack lieber deine 400 Hz Multiplexroutine in 
deinen 5 kHz ISR und löse bei jeder 12. ISR das Multiplexen aus.
Alternativ kann amn das Multiplexen in die Hauptschleife verlegen und 
per Flag signalisieren. Damit ist es auch problemlos und sauber durch 
die ADC-Interrupts unterbrechbar, siehe Interrupt.


>Wird das so funktionieren?

Du machst dir viel zu viel Stress. Ausserdem kannst du den ADC per 
Interrupt auch prima als Timer missbrauchen. Durch richtige Wahl des 
Vorteilers und Freerun Mode kannst du auch den Timer COMPA Interrupt 
verzichten und alles wird einfacher.

MFg
Falk

von Jörg G. (joergderxte)


Lesenswert?

>TIMER0_COMP_vect:
>5Khz
>Triggert die Erste von zwei AD-Wandlungen (Spannung).
>>ADC-Ergebnisse der letzten Messugen multiplizieren und integrieren
Dass klingt nicht sehr gut, besser:
- der 5kHz-timer triggert die erste messung
- der ADC-Interrupt (state-machine) puffert die erste und startet die 
zweite Messung
- der ADC-Interrupt puffert die 2. Messung, setzt ein 
Messung-fertig-flag und schaltet sich ab
- die Mainloop multipliziert/integriert immer wenn's passt (d.h. das 
Flag gesetzt ist)

hth, Jörg
ps.:
wenn du tatsächlich Interrupt-Prioritäten nutzen willst, gehört das 
sei()-cli() in die Routine, die unterbrochen werden darf , also die 
Timer1-routine

pps.: Wie falk sagte, kannst du die Timer-ISRs auch gleich noch zusammen 
legen, da du das Multiplexen auch per Flag erledigen lassen kannst (ganz 
besonders, wenn das unterbrochen werden darf).

edit: Shift-Taste repariert ;)

von Andreas R. (rebirama)


Lesenswert?

Danke für die Tipps.


Multiplexen in der Main fällt aus, da dort später (noch nicht 
implementiert) lang dauernde Rechnungen stattfinden (Effektivwerte, 
Blindleistung etc), da würde eventuell Multiplexen aus dem Tritt kommen.

Alles in die 5Khz-ISR packen (Integrieren von U*I, I², U², Multiplexen) 
könnte funktionieren.
Die kann dann bein Eintreffen des ersten und des zweiten Ergebnisses vom 
ADC unterbrochen werden.(sei(); zu beginn der ISR)
Einmal pro Sekunde würden die über diesen Zeitraum integrierten Werte 
dann an die Main übergeben zwecks weiterer Auswertung.

Ich denk ich werde beide Versionen ausprobieren. Beim Basteln ist ja der 
Weg das Ziel ;-)

@jörg: es ist mir schon klar, dass ich sei(); in der unterbrechbaren ISR 
schreiben muss. Ich Will nur wissen, ob man mit dem Konstrukt aus meinem 
Post 3 verschiedene IR-Prioritäten realisieren kann:
Timer1: unterbrechbar von Timer0 und ADC
Timer0: unterbrechbar von ADC
und ob ein anstehender Timer1 erst nach Ende der timer0-ISR ausgeführt 
würde.

Was mir gerade noch auffällt: Bevor man in einer ISR sei(); setzt sollte 
man die enable flag des (selben) interrupts clearen, damit sich im 
Worscase der Interrupt nicht selbst unterbricht

Grüße

von Falk B. (falk)


Lesenswert?

@  Andreas R. (rebirama)

>Multiplexen in der Main fällt aus, da dort später (noch nicht
>implementiert) lang dauernde Rechnungen stattfinden (Effektivwerte,
>Blindleistung etc), da würde eventuell Multiplexen aus dem Tritt kommen.

Bist du SO erfahren in der Programierung, dass du das mal fix 
ausschliessen kannst?

Schau dir mal an wie man sowas macht.

http://www.mikrocontroller.net/articles/Multitasking#Ein_einfaches_Beispiel_f.C3.BCr_den_AVR

>Alles in die 5Khz-ISR packen (Integrieren von U*I, I², U², Multiplexen)
>könnte funktionieren.

Muss man mal simulieren.

>Die kann dann bein Eintreffen des ersten und des zweiten Ergebnisses vom
>ADC unterbrochen werden.(sei(); zu beginn der ISR)

Lass den Unsinn. Der bringt mehr Stress als Gewinn.

>Post 3 verschiedene IR-Prioritäten realisieren kann:
>Timer1: unterbrechbar von Timer0 und ADC
>Timer0: unterbrechbar von ADC
>und ob ein anstehender Timer1 erst nach Ende der timer0-ISR ausgeführt
>würde.

Alles viel zu kompliziert und unnötig. Einzig und allein die ADC-Messung 
muss ein sehr genaues Timing haben, der Rest kann jittern und ein paar 
hundert us Delays haben, interessiert keinen.

MFG
Falk

von Gast (Gast)


Lesenswert?

Und ehrlich: Ne Samplingfrequenz von 1.6 kHz statt 5 kHz tuts auch (= 32 
Samples pro 50 Hz-Schwingung). Bei nem Systemtakt von 16 Mhz hast Du 
dann von einem Sample bis zum nächsten 10000 Zyklen Zeit. Da kann man 
schon ne anständige Rechnerei veranstalten.

von Andi (Gast)


Lesenswert?

@Gast: es sind leider nicht nur 50Hz, z.B. eine Energiesparbirne, die 
ihren Netzelko in ner ms auffüllt. Wenn der Impuls gerade ungünstig 
zwischen zwei Samples liegt, zeigt das Messgerät zu wenig an.

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.