Forum: Compiler & IDEs Variablenprobleme im Interrupt


von Alex (Gast)


Lesenswert?

Hallo zusammen,

wieder einmal etwas von mir. Ich bin mir gerade ein Programm zum 
Einlesen von RC-Kanälen am machen. Ich habe mich für eine nicht ganz 
sooo schöne Lösung für einen Mega8 entschieden, da ich nur solche 
besitze und nicht auf andere warten will.
Die Lösung ist für max. 7 Kanäle und man darf nur eine ungerade Anzahl 
einlesen. Dabei muss man die Kanäle 1,3,5,7 (sofern so viele vorhanden, 
geht auch mit weniger) über Dioden an Int0 anschliessen. Die Kanäle 
müssen von einem Empfänger sein. Die Kanäle 2,4,6 müssen nicht 
angeschlossen werden (dürfen auch nicht).
Das gibt mir ein schönes Rechtecksignal, welches ich über int0 auslesen 
kann.
Es funktioniert alles fast wie es sollte. Nur noch kleine Sachen gehen 
nicht wie sie sollen. Jedenfalls kann ich das Signal auswerten und ich 
habe alles geprüft. (habe es erst mit einem Kanal versucht, aber sollte 
auch mit mehr gehen.)
Nun gibt es aber ein Problem, das ich nicht begreife. Der Anfang meines 
int0 Interrupts sieht so aus:
1
ISR(INT0_vect)
2
{
3
  uint16_t templaenge2;
4
  uint16_t templaenge;
5
  
6
  templaenge = (anzovfl << 8); //anz. Overflows seit letztem Flankenwechsel * 256
7
  templaenge += TCNT2; //Noch den aktuellen Timerwert dazu zählen
8
        //KONTROLLPUNKT
9
  templaenge2 = (uint16_t) templaenge / rcin_mikro_10; //Den Wert auf 100stel Millisekunden umwandeln.
10
  
11
  anzovfl = 0; //anz. overflows wieder auf 0
12
  TCNT2 = 0; // Timer auf 0
13
  ...
Wie gesagt, so funktioniert alles. Nun finde ich das aber recht unschön 
und ich will hier alles mit einer tempvariablen machen. Dann sieht der 
Code so aus:
1
ISR(INT0_vect)
2
{
3
  //uint16_t templaenge2;
4
  uint16_t templaenge;
5
  
6
  templaenge = (anzovfl << 8); //anz. Overflows seit letztem Flankenwechsel * 256
7
  templaenge += TCNT2; //Noch den aktuellen Timerwert dazu zählen
8
  //KONTROLLPUNKT
9
  templaenge/*2*/ = (uint16_t) templaenge / rcin_mikro_10; //Den Wert auf 100stel Millisekunden umwandeln.
10
  
11
  anzovfl = 0; //anz. overflows wieder auf 0
12
  TCNT2 = 0; // Timer auf 0
13
  ...
In der ersten (unschönen) Variante geht alles wie es sollte und beim 
KONTROLLPUNKT kommt ein Wert, der dem Timerabstand seit dem letzten 
Flankenwechsel entspricht.
Bei der zweiten Variante kommt beim KONTROLLPUNKT (der noch VOR der 
Änderung des Codes liegt!!!!!) immer der selbe Wert.
Beim Rest des Interruptcodes ersetze ich einfach noch an einer Stelle 
das templaenge2 mit templaenge.
An was liegt dieses Komische verhalten?

Grüsse Alex

von Frank L. (franklink)


Lesenswert?

Hallo Alex,

definier mal die Variable templaenge als

static uint16_t templaenge;

Das sollte genügen.

Gruß
Frank

von (prx) A. K. (prx)


Lesenswert?

Muss die Division unbedingt in den Interrupt? Ist recht langsam und wird 
evtl. in der Varianten vom Compiler etwas herumgschoben.

Müsste man ansonsten den erzeugten Code ansehen.

von (prx) A. K. (prx)


Lesenswert?

Was soll das "static" bringen, abgesehen von schlechterem Code?

von Alex (Gast)


Lesenswert?

Das static bringt nichts. Ich werde es mal mit einer klugen 
initialisierung des Timers probieren, um die / Rechnung wegzubekommen.
Danke schon mal für die vielen Antworten. Ich werde dann schreiben ob es 
klappt!
Grüsse Alex

von Alex (Gast)


Lesenswert?

Nun habe ich es fangs zum einen Teil geschafft. Ich hatte das Prescaling 
des 8-Bit Timers2 vorher auf 8. Da ich mit 1 MHz arbeite (interner 
Takt), ergab das einen Wert von 1.25, durch den ich rechnen musste. Das 
hat anscheinend diese schwierigkeiten verursacht. Nun habe ich kein 
Prescaling mehr und kann durch 10 rechnen. Das macht er problemlos. Das 
ist jedoch nicht gerade eine gute Lösung, da ich diese Routine auch 
später noch einsetzen will mit anderen Takten. Wie könnte ich hier eine 
allgemeingültige Lösung finden?

Grüsse Alex

von Karl H. (kbuchegg)


Lesenswert?

Setz an deiner Auswertung an.
Wenn du dort einfach berücksichtigen kannst, dass alle Werte das 
Zehnfache von vorher sind, dann brauchst du gar nicht durh 10 
dividieren.

von Alex (Gast)


Lesenswert?

Ich will aber machen, dass das Programm für spätere Anwendungen nur 
eingebunden und die Taktfrequenz angepasst werden muss. Dann will ich 
nicht den ganzen Code ändern... Somit könnte es einiges komplizierter 
werden.
Noch eine Frage dazu:
Wenn ich ein #define mache, z.B.:
1
#define MEINDEFINE1 100000
2
#define MEINDEFINE2 MEINDEFINE1/50
Nur so als Beispiel. Wird jetzt MEINDEFINE2 schon im Präprozessor 
berechnet und überall mit dem Ergebnis ersetzt, oder erst an der Stelle, 
an der ich es Anwende beim Programmlauf(z.B. bei jedem Programmdurchlauf 
neu berechnet?)?

von Karl H. (kbuchegg)


Lesenswert?

Alex wrote:

> Wenn ich ein #define mache, z.B.:
>
1
> #define MEINDEFINE1 100000
2
> #define MEINDEFINE2 MEINDEFINE1/50
3
>
> Nur so als Beispiel. Wird jetzt MEINDEFINE2 schon im Präprozessor
> berechnet

http://www.mikrocontroller.net/articles/C-Pr%C3%A4prozessor#.23define

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.