Phänomen oder Fehlbedienung?!

Gast #2090402
Lesenswert?

Hallo zusammen,

ich steige bei meinem Programm nicht hinter das Problem.

Im Anhang findet Ihr den Code eines -wie ich finde- sehr simplen 
Programmes.

Es soll nicht mehr passieren, als dass von einem Zählwert der in der ISR 
inkrementiert wird, auf Port C ein einzelnes Bit angezeigt wird.

Jetzt zum Problem:

Wenn (wie im Codebeispiel) die Zeilen
1
if (clock0.taktbyte.bit2 == 1)
2
{
3
  PORTC |= (1 << PC2);
4
}
5
else
6
{
7
  PORTC &= ~(1 << PC2);
8
}

in der Endlosschleife stehen, bleibt der Wert an PORT C auf 0x00.

Stehen diese Zeilen stattdessen in der ISR...:
1
SIGNAL(SIG_OVERFLOW0)
2
{
3
  TCNT0 = STARTVAL_DEB;
4
  
5
  clock0.cval++;
6
  
7
  if (clock0.taktbyte.bit2 == 1)
8
  {
9
    PORTC |= (1 << PC2);
10
  }
11
  else
12
  {
13
    PORTC &= ~(1 << PC2);
14
  }
15
}

... macht das Programm was es soll und PC2 blinkt.

Kann mir jemand sagen, was ich falsch mache?

Danke für jeden Tipp!!

Grüße

Dennis
Angehängte Dateien:
Gast #2090458
Lesenswert?

Hast Du denn ein volatile vor dem union schon ausprobiert? Vermutlich 
ist es so wie Christopher sagt: clock0.taktbyte.bit2 wird in der 
while-Schleife nicht verändert, deshalb optimiert der Compiler rigoros 
weg, was danach passieren soll.

Mirko
Gast #2090467
Lesenswert?

Den 'else' Teil aus 'main' übersetzt der Compiler dank der Optimierung 
in einen Kreisverkehr (sieh Code 1).

Lösung: 'volatile' vor der 'union' (Code 2).

Code 1

    {
      PORTC &= ~(1 << PC2);
    }


+00000049:   98AA        CBI       0x15,2         Clear bit in I/O 
register
+0000004A:   98AA        CBI       0x15,2         Clear bit in I/O 
register
+0000004B:   CFFD        RJMP      PC-0x0002      Relative jump

Code 2

60:           if (clock0.taktbyte.bit2 == 1)
+00000042:   91800060    LDS       R24,0x0060     Load direct from data 
space
+00000044:   FF82        SBRS      R24,2          Skip if bit in 
register set
+00000045:   C005        RJMP      PC+0x0006      Relative jump
62:             PORTC |= (1 << PC2);
+00000046:   9AAA        SBI       0x15,2         Set bit in I/O 
register
60:           if (clock0.taktbyte.bit2 == 1)
+00000047:   91800060    LDS       R24,0x0060     Load direct from data 
space
+00000049:   FD82        SBRC      R24,2          Skip if bit in 
register cleared
+0000004A:   CFFB        RJMP      PC-0x0004      Relative jump
66:             PORTC &= ~(1 << PC2);
+0000004B:   98AA        CBI       0x15,2         Clear bit in I/O 
register
+0000004C:   CFF5        RJMP      PC-0x000A      Relative jump
66:             PORTC &= ~(1 << PC2);
Gast #2090574
Lesenswert?

Vermutung:

1. Nach dem Tip
>Stichwort volatile.
>Der Compiler sieht in der Main keinen schreibenden Zugriff, also denkt
>er, der Wert kann sich gar nicht ändern.

und der Antwort:

"... wenn ich aus der Main in ein Unterprogramm springe."

hat der TO wahrscheinlich nicht das fehlen von volatile als eigentliche 
Ursache verstanden, sondern ein Problem in speziell der Verbindung von 
main und dem fehlenden schreibenden Zugriff gesehen, das er mit der 
Benutzung einer Unterfunktion (die dann natürlich nicht main heisst) 
beheben wollte.

Die Erklärung dazu, dass durch die fehlende Änderung an der Variablen 
der Compiler den Zugriff wegoptimiert, hat er nicht als allein 
hinreichend wahrenommen.

Das das Problem grundsätzlich auf jede Funktion zutrifft war aus dem 
Satz nicht wirklich zu erkennen. Vielmehr muss der Anfänger den Satz 
wörtlich nehmen und ihn, wie vermutlich geschehen auf die Funktion main 
und den fehlenden schreibenden Zugriff in Konjunktion beziehen. Das er 
das zu umgehen versucht, in dem er nur eine der beiden 
Bestimmungsgrössen ändert ist für mich durchaus verständlich und 
konsequent.

Der Antworter hat main hier nicht als konkrete Ausprägung einer 
grösseren Menge von Fällen dargestellt, sondern (sehr wahrscheinlich 
unabsichtlich) suggeriert, dass main selbst auch eine Ursache des 
Problems ist.
Gast #2090581
Lesenswert?

Man könnte noch hinzufügen, das durch die Tatsache das volatile fehlt 
die Ursache allein schon hinreichend beschrieben ist. Denn ein Zugriff 
auf eine Variable kann (abgesehen von der Initialisierung) ohnehin in C 
nur innerhalb einer Funktion erfolgen.

Somit ist der Zusatz "in main" oder auch "in einer Funktion" in 
zweifacher Hinsicht irreführend, denn selbst der fortgeschrittene 
Anfänger könnte unter Beachtung eben dieser Tatsache auf den Gedanken 
kommen, das main eine Sonderrolle spielt, zumal dies in anderer Hinsicht 
auch der Fall ist, weil main die einzige Funktion ist, die er nicht 
ausdrücklich aufzurufen braucht, so das ihm die suggerierte Sonderrolle 
von main in Bezug auf volatile nicht unplausibel scheinen mag.

Ich möchte noch hinzufügen, dass ich mit dieser Kritik den Antworter in 
keiner Weise herabsetzen möchte. Ich hoffe nur, damit die Qualität der 
Antworten hilfreich zu beeinflussen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren