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_tCurrent,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
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
@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
>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 ;)
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
@ 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
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.
@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.