Forum: Compiler & IDEs Kein Zugriff auf globale Variable im Interrupt


von Markus Wucher (Gast)


Lesenswert?

Hallo!
Ich habe hier einen ATtiny24 an dessen PortA eine 7-Segment-Anzeige und 
an Port B zwei LEDs hängen. Die 7-Segment anzeige soll immer im Kreis 
von 0-F zählen und die LEDs dazu blinken. Das ganze läuft über einen 
Timer-Interrupt, der die LEDs toggeln und den Wert für die Anzeige um 1 
erhöhen soll. Das klappt auch alles prima, bis auf die Erhöhung der 
Variablen, obwohl sie mit "volatile" deklariert ist! Die anzeige bleibt 
immer auf dem ersten Wert (7) stehen. Was mache ich falsch???

Vielen Dank für eure Hilfe!

Markus

von Dirk (Gast)


Lesenswert?

Ohne Code schwer zusagen.

Ist die Variable wirklich Global und volatile?

volatile unsigned char uzibuz=0;

Gruß,
Dirk

von Markus Wucher (Gast)


Angehängte Dateien:

Lesenswert?

Sorry war grad zu doof den Code mitzuschicken.

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Der Code sieht soweit eigentlich nicht schlecht aus (wenn ich nichts 
übersehen habe). Was evtl. noch sein könnte ist, dass deine globale 
Variable in dem Includefile für die Interruptverarbeitung nicht bekannt 
ist und daher nicht angesprochen werden kann?!? Aber müsste der Compiler 
dann nicht nen Fehler melden?

Was ich allerdings unschön finde ist der Funktionsaufruf innerhalb der 
Interruptroutine um die LEDs zu togglen. Realisiere das togglen doch 
einfach durch den Zweizeiler:

PORTB ^= (1 << LED1_POS);  //LED1 togglen
PORTB ^= (1 << LED2_POS);  //LED2 togglen

oder den Einzeiler:

PORTB ^= (1 << LED1_POS) | (1 << LED2_POS);  //LED1 & 2 togglen


Gruß,

Thomas

von Markus Wucher (Gast)


Lesenswert?

Ich hab durch Thomas' Anregung ein bisschen mit den LEDs gespielt. Wenn 
ich versuche sie mit xor umzuschalten, muss ich sie in main ja 
initialisieren. und diesen 1. Zustand behalten sie dann. Man sieht nur 
ein ganz kleines Blitzen. Also irgendwie läuft mein Programm 
gelegentlich von vorn los, kann das sein?? oder ich häng irgendwo? Das 
würd auch das 1. Problem erklären.

von pumpkin (Gast)


Lesenswert?

Hast du den watchdog und brown out mal geprüft? Wie ist der Interrupt 
zeitlich eingestellt?

pumpkin

von Werner B. (Gast)


Lesenswert?

Tipp: Verwende eine temporäre Variable zur Ausgabe.

Statt
1
while (1) {
2
  count &= 0x0f;
3
  PORTA = ~seg_code[count];
4
  }
1
unsigned char temp;
2
3
while (1) {
4
        temp = count;
5
  temp &= 0x0f;
6
  PORTA = ~seg_code[temp];
7
  }
denn zwischen "count &=" und der Ausgabe auf PORTA kann die ISR 
zuschlagen.

Zum Problem:

Ich nehme mal an der Counter wird nicht richtig initialisiert. Kann 
jetzt nicht nachsehen, aber der Tiny45 kann doch sicherlich den CTC 
Mode?!
Für solche Aufgaben (regelmäßige Interrupts) ist der besser geeignet.

Werner

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Laut Datenblatt müsste der Timer eigentlich so funktionieren wie Markus 
das macht. Ich hab im Datenblatt aber gerade noch die folgenden zwei 
Sätze gefunden:

Modifying the counter (TCNT1) while the counter is running introduces a 
risk of missing a compare match between TCNT1 and one of the OCR1x 
Registers.

Writing to the TCNT1 Register blocks (removes) the compare match on the 
following timer clock for all compare units.

Deine Programmzeile

TCNT1=0; //Timer wieder starten

in der Interruptroutine startet den Timer ja nicht neu, sondern setzt 
den Zählerstand des Timers nur wieder auf 0. Versuch mal vor diesem 
Schreibzugriff auf den Timer diesen anzuhalten und direkt nach dem 
Schreibzugriff wieder zu starten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> #define __AVR_ATtiny24__

You are not supposed to do this!

Symbole, die mit zwei Unterstrichen anfangen sind (sofern nicht
ausdrücklich durch die Dokumentation authorisiert) für dich als
Endanwender tabu.

Da du das da obendrüber geschrieben hast, lässt mich das ganz
stark vermuten, dass du vergessen hast, beim Compilieren und
beim Linken -mmcu=attiny24 mit anzugeben.  Wenn du das nämlich
ordnungsgemäß machst, generiert der Compiler nicht nur ordentlichen
Code für deinen ATtiny24, sondern der Präprozessor kennt auch den
obigen Macro.  Wenn du das beim Linken auch noch mit dabei hast,
bekommst du zur Belohnung sogar noch die passende Interruptvektor-
tabelle für deinen ATtiny24 statt die für einen AT90S8515...

von Markus Wucher (Gast)


Lesenswert?

Hab gerade das Symbol _AVR_ATtiny24_ weggemacht, und im Makefile MCU = 
attiny24 eingetragen.
Allerdings kann er jetzt gar nicht mehr kompilieren, da:
unknown MCU 'attiny24' specified
Known MCU names:
...
...

..nur kein tiny24

Hab ich da ne zu alte avr-libc, oder muss ich was anderes wählen? 
(vorher war avr2 eingestellt, dann kennt er aber auch eine Symbole des 
tiny24, eben nur durch das Symbol _AVR_ATtiny24_ )

Danke für eure Tipps!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Hab ich da ne zu alte avr-libc

Die gesamte Toolchain ist dann offenbar zu alt.  Wenn's denn ,,nur''
der Compiler wäre (die avr-libc aber den Prozessor kennt), könnte dir
der Trick mit dem _AVR_ATtiny24_ ja noch helfen, aber dann müsstest
du den Linker mit der Hand aufrufen, damit die crttn24.o ordentlich
gelinkt wird.

von Markus Wucher (Gast)


Lesenswert?

Hab mir da irgendwie gar keine Gedanken über das Alter der Toolchain 
gemacht, weil ichs in Ubuntu aus dessen Repositories installiert hab. 
Aber hier ist glaub alles bisschen alt. simulavr kennt z.B. fast gar 
nix... Werd nächste woche mal alles auf den neuesten Stand bringen, dann 
wirds wohl klappen. Danke!

Gruß Markus

von Frank J. (frajo)


Lesenswert?

Im aktuellen Ubuntu 7.04 ist AVR Libc 1.4.5 und GCC 4.1.0 dabei.

von Markus Wucher (Gast)


Lesenswert?

Jetzt tut's wie gewünscht, vielen Dank. Habe die "cdk"-Pakete von 
sourceforge installiert.
Mit den ubuntu-paketen gings nicht, da kennt avr-gcc keinen attiny24.

Grüße Markus

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.