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


von Thomas D (Gast)


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:
1
int inputEnable=1;
2
3
int main(void)
4
{
5
  int temp;
6
  init();
7
  while(1)
8
  {
9
    if(inputEnable==0)    // Spieler hat einen Stein gesetzt
10
    {
11
      feld[0][0]=1;    
12
    }
13
  }
14
  return 0;
15
}


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

von was-willst-du (Gast)


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?

von Felix N. (time2ride)


Lesenswert?

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

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Hi,

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

Gruß, Lasse

PS: Ok, Felix war schneller ;)

von Thomas D (Gast)


Angehängte Dateien:

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.

von Thomas D (Gast)


Lesenswert?

Alles klar Danke!!!

von Thomas D (Gast)


Lesenswert?

Geht leider trotzdem noch nicht.

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Dann poste bitte mal den kompletten Code!

Gruß, Lasse

von Thomas D (Gast)


Angehängte Dateien:

Lesenswert?

Der ist ziemlich lang. Als Anhang...

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Kann es sein, dass die Timerroutine das Flag wieder löscht?

Teste doch mal nur den minimalnotwendigen Code.

von Thomas D (Gast)


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.

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Im Interrupt setzt du aber auch

inputEnable=0;

von Stefan E. (sternst)


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:
1
    if(inputEnable==0)    // Spieler hat einen Stein gesetzt
2
    {
3
      (volatile int)feld[0][0]=1;    
4
    }

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.

von Thomas D (Gast)


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.

von Lasse S. (cowz) Benutzerseite


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

von Thomas D (Gast)


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.

von Lasse S. (cowz) Benutzerseite


Lesenswert?

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

von Stefan E. (sternst)


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.

von Thomas D (Gast)


Lesenswert?

Wie und wann löscht er sie denn?

von Stefan E. (sternst)


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:
1
*(volatile int*)&feld[0][0] = 1;

von Thomas D (Gast)


Lesenswert?

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

von Lasse S. (cowz) Benutzerseite


Lesenswert?

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

von Thomas D (Gast)


Lesenswert?

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

von Thomas D (Gast)


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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

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.