Moin Leute,
das Problem das mir mittlerweile Kopfschmerzen macht ist:
Ich habe in der "int main(void)" ein Array definiert "int zeit[8];".
Jetzt wird die Interruptroutine "ISR(TIMER1_OVF_vect)" ausgeführt. In
dieser Interrupt Routine möchte ich das Integer Array aus der Main
verändern. Die Veränderung soll später in der Main verfügbar sein.
Ich programmiere einen ATmega644 mit WinAVR im AVRstudio.
Vielen Dank für Eure Hilfe!
Gruß,
Christian.
Das wird ohne Änderungen des Designkonzepts nicht gehen.
Ich verstehe Dich etwa so:
1
INTERRUPT(...)
2
{
3
böses_array[13]=irgendwas;// geht nicht
4
nochwas=bböses_array[7];// geht nicht
5
}
6
7
main()
8
{
9
charboeses_array[1234];
10
}
Auf diese Weise ist aber in der Interruptroutine das böse array garnicht
sichtbar. Es ist nur_ und _ausschliesslich innerhalb von main
sichtbar.
Du hast nun zwei Möglichkeiten, die aber letztlich darauf hinauslaufen
eine Variable zu definieren, die zumindest innerhalb der
Quelltexteinheit sichtbar ist (wenn nicht im gesamten Projekt).
Hier also die im allgemeinen gewählte Variante
1
volatilechargutes_array[1234];
2
3
INTERRUPT(...)
4
{
5
gutes_array[2]=schoenes;
6
bedeutendes=gutes_array[4];
7
}
8
9
main()
10
{
11
// irgendwas nettes
12
}
Die zweite Variante deklariert einen globalen Zeiger auf das Array.
Beachte, das kein Interrupt auftreten darf, ehe x gesetzt ist.
Moin!
Herzlichen Dank! Man war ich verbohrt, klar, so geht es! Danke! Bin aus
diesem Übergabe-Denken nicht raus gekommen, anstatt es einfach mal
"global" zu machen.
Vielen Dank noch mal!
Christian.
> Du hast nun zwei Möglichkeiten, die aber letztlich> darauf hinauslaufen eine Variable zu definieren,> die zumindest innerhalb der Quelltexteinheit sichtbar> ist (wenn nicht im gesamten Projekt).> Hier also die im allgemeinen gewählte Variante ...> Die zweite Variante deklariert einen globalen Zeiger> auf das Array. Beachte, das kein Interrupt auftreten> darf, ehe x gesetzt ist.
Was ist der Vorteil der zweiten Variante gegenüber der ersten? Ich kann
keinen erkennen. Nachteile sind dagegen erheblich:
1. Du sagst es schon, man muss verhindern, dass ein Interrupt ausgelöst
wird, bevor die Zeigervariable vorbereitet ist.
2. Globale Zeiger auf lokale Daten und Schreibzugriff zu unbestimmten
Zeitpunkten - ganz böse. Ist hier nur deshalb nicht tragisch weil man in
der Main-Funktion normalerweise immer drin bleibt. Bei jeder anderen
Funktion, die auch wieder verlassen werden kann, wäre das der sichere
Weg zur Stack-Corruption - absolut tödlich fürs Programm.
3. Das Ganze ist offenbar derart kompliziert, dass du selber drei
Anläufe gebraucht hast, um es richtig hinzuschreiben.
4. Obendrein muss man sich Gedanken darum machen, ob char * volatile x
wirklich dasselbe ist wie volatile char * x - ich bin mir da nicht
sicher, hab aber keine Lust, drüber nachzudenken, weil ich so (aus o.g.
Gründen) nie programmieren würde.
Moin!
Ja dein Einwand ist mehr als berechtigt, ist aber für mich erst mal kein
Problem. Die Interruptroutine dient nur, um einen Zähler im Sekundentakt
hoch oder runter zu zählen. Erst wenn der Zähler und damit der Interrupt
abgestellt ist, möchte ich den letzten Wert des Zählers in das Array
speichern. Sprich, wenn ich auf das Datenelement zugreife, kann
programmtechnisch kein Interrupt mehr aktiv sein, der diese Daten
korrumpieren könnte.
Nichts desto trotz interessiert mich, falls du magst, der saubere
Lösungsansatz sehr. Wenn ich mich nicht irre kann man ja einer Interrupt
Routine keine Werte übergeben oder welche zurückgeben. Wie kann man also
Ergebnisse aus einer Interrupt Routine in den sonstigen Programmlauf
einbringen ohne globale Variablen?
Gruß,
Christian.
Christian Blank wrote:
> Ergebnisse aus einer Interrupt Routine in den sonstigen Programmlauf> einbringen ohne globale Variablen?
Gar nicht.
Egal welchen Weg du gehst, es ist immer mindestens eine globale
Variable beteiligt.
tuppes wrote:
> Was ist der Vorteil der zweiten Variante gegenüber der ersten? Ich kann> keinen erkennen. Nachteile sind dagegen erheblich:
Es gibt durchaus sinnvolle Anwendungen für sowas.
> 1. Du sagst es schon, man muss verhindern, dass ein Interrupt ausgelöst> wird, bevor die Zeigervariable vorbereitet ist.
Sinnvollerweise überprüft man in der ISR den Pointer erstmal auf
ungleich 0.
> 2. Globale Zeiger auf lokale Daten und Schreibzugriff zu unbestimmten> Zeitpunkten - ganz böse. Ist hier nur deshalb nicht tragisch weil man in> der Main-Funktion normalerweise immer drin bleibt. Bei jeder anderen> Funktion, die auch wieder verlassen werden kann, wäre das der sichere> Weg zur Stack-Corruption - absolut tödlich fürs Programm.
Man benutzt sowas normalerweise nur mit statischen lokalen Variablen,
nicht mit automatischen.
> 4. Obendrein muss man sich Gedanken darum machen, ob char * volatile x> wirklich dasselbe ist wie volatile char * x - ich bin mir da nicht> sicher, hab aber keine Lust, drüber nachzudenken, weil ich so (aus o.g.> Gründen) nie programmieren würde.
Was hat das miteinander zu tun? Bei einem Pointer muss man sich doch
immer Gedanken machen, ob der Pointer selber, oder das Ziel des Pointers
volatile sein muss.
> Es gibt durchaus sinnvolle Anwendungen für sowas.> Man benutzt sowas normalerweise nur mit statischen> lokalen Variablen, nicht mit automatischen.
na gut, meinetwegen. Das ist zumindest nicht so gefährlich.
Aber trotzdem bleibt die Geschichte kompliziert. Die Funktion, die die
Variable besitzt, muss einmal gelaufen sein, damit der Pointer gesetzt
ist.
Bei diesem ersten Durchlauf darf sie die Daten in der Variablen noch
nicht benutzen, das darf sie erst, nachdem sie den Pointer gesetzt hat
UND DANACH der Interrupt einmal gekommen ist und die Variable mit was
Sinnvollem gefüllt hat.
Die ISR ihrerseits muss zeitlebens den Pointer gegen 0 checken, bevor
sie Daten setzen darf.
Ganz schön viel Protokoll.