www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik "if(globaleVariable==0)" funktioniert nicht


Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich habe hier eine selbst gebaute 3x3 LED-Matrix und eine 3x3 
Tastermatrix.

Die LEDs und Taster werden mit ca 100 Hz durch Interrupt angesteuert.

Wenn ein Taster gedrückt wird, wird die globale Variable inputEnable im 
Interrupt auf 0 gesetzt und die zum Taster entsprechende LED leuchtet.

Komischerweise erkennt er if(inputEnable==0) nicht in der while 
Schleife. Hier der Code:

int inputEnable=1;

int main(void)
{
  int temp;
  init();
  while(1)
  {
    if(inputEnable==0)    // Spieler hat einen Stein gesetzt
    {
      feld[0][0]=1;    
    }
  }
  return 0;
}


Zum Testen soll also einfach die LED in der Ecke [0][0] angehen. Tut sie 
aber nicht.

Autor: was-willst-du (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn das Programm die Gleichheit nicht feststellt, so wird sie auch 
nicht vorhanden sein. Der Wunsch hilft da nicht.

Was passiert in der Interruptroutine?

Autor: Felix Nachname (time2ride)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile int inputEnable=1;
Ist des Rätsels Lösung, da der Compiler die Variable sonst wegoptimiert.

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Globale Variablen, die in Interrupts verwendet werden müssen als 
volatile deklariert werden.

Gruß, Lasse

PS: Ok, Felix war schneller ;)

Autor: Thomas D (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oh, tut mir Leid hab ich vergessen:

Ich weiß, dass interruptEnable==0 ist da das anschalten der anderen LEDs 
gesperrt ist. Ich häng mal das File an. Gleich oben ist der Interrupt. 
Egal welchen Taster man drückt, die entsprechende LED geht an. Danach 
sind die anderen gesperrt und trotzdem leuchtet die LED in der Ecke 
nicht.

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar Danke!!!

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht leider trotzdem noch nicht.

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann poste bitte mal den kompletten Code!

Gruß, Lasse

Autor: Thomas D (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Der ist ziemlich lang. Als Anhang...

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass die Timerroutine das Flag wieder löscht?

Teste doch mal nur den minimalnotwendigen Code.

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Der Timer wird alle 0,01/3 s neu gestartet und dabei der Interrupt 
ausgelöst. Das Programm ist ja schon sehr reduziert. Die ganzen 
Funktionen unten werden garnicht benutzt. Durch den Interrupt weiß ich 
ja, dass darin inputEnable!=1. In der while Schleife kapiert er das 
nicht.

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Interrupt setzt du aber auch

inputEnable=0;

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
feld[0][0] muss hier auch volatile sein, um ein Zurückschreiben der 
geänderten Variable in der Schleife zu erzwingen. Ein lokaler Cast wäre 
hier das Beste:
    if(inputEnable==0)    // Spieler hat einen Stein gesetzt
    {
      (volatile int)feld[0][0]=1;    
    }

PS: Und mache dir mal Gedanken über die Größe der Variablen. Die sind 
alle größer als nötig, was eine schlechte Idee ist.

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Richtig. Und in der while(1) Schleife in der Main steht, dass dann das 
feld[0][0]=1;

Demach müsste jetzt die LED in der Ecke leuchten. Tut sie aber nicht.

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Interrupt setzt inputEnable=0;. Kein Wunder, dass du das in der Main 
nicht mehr mitbekommst...

Alternativ: Kann es sein, dass die LED einfach nur nicht leuchtet, weil 
beim Anzeigemechanismus was kaputt ist? Mal ohne die If-Abfrage einfach 
direkt gesetzt?

Gruß, Lasse

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(volatile int)feld[0][0]=1;

main.c:188: error: lvalue required as left operand of assignment



Ich hatte neulich Probleme mit chars, da hab ich jetzt erstmal int 
genommen. Der Platz reicht schon aus.



Alternative stimmt auch nicht. Ich kann überall wo er sonst durchgeht 
feld[0][0]=1 setzten und die LED leuchtet. Das geht mit allen LEDs.

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und die nicht Alternative, dass er das im Interrupt löscht ignorierst du 
einfach mal so? ;)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lasse S. wrote:
> Und die nicht Alternative, dass er das im Interrupt löscht ignorierst du
> einfach mal so? ;)

Das ist doch genau das, was er will. Er fragt doch in main auf Null ab.

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie und wann löscht er sie denn?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas D wrote:
> (volatile int)feld[0][0]=1;
>
> main.c:188: error: lvalue required as left operand of assignment

Dann eben mit etwas Verrenkung:
*(volatile int*)&feld[0][0] = 1;

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Löschen im Sinne von =0 setzen. Ja, das soll er. Und die main erkennt es 
nicht.

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hust ;) Stimmt ja, sorry... Zu spät, ich geh dann jetzt mal lieber ins 
Bett ;)

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und es klappt tatsächlich. Was auch immer in dieser Zeile geschehen 
mag... sie funktioniert. Danke!!!

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, da dies nur ein kleiner Test war und ich das Feld ziemlich oft 
brauche kommt es immer wieder zu Fehlern.


Wie schafft man es also ein Feld sowohl in einem Interrupt als auch in 
der main Funktion schreiben/lesen zu können.


Reicht es wenn ich das Feld ebenfalls

volatile

definiere?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> also ein Feld sowohl in einem Interrupt als auch in
> der main Funktion schreiben/lesen zu können.
Das ist eher ein Kapselungsproblem (Semaphore). Du darfst nicht 
gleichzeitig vom Interrupt und vom Hauptprogramm aus auf das selbe 
Element im Feld schreibend zugreifen. Das geht garantiert schief.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.