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
Das Problem ändert sich auch nicht, wenn ich aus der Main in ein
Unterprogramm springe. Was muss ich denn machen, damit der Compiler
dieses Denken sein lässt?
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
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);
Dennis schrieb:> Mirko schrieb:>> Hast Du denn ein volatile vor dem union schon ausprobiert?>> Ja, das habe ich ausprobiert. Das Problem besteht weiterhin.Martin schrieb:> Lösung: 'volatile' vor der 'union' (Code 2).Dennis schrieb:> @Mirko && Martin:>> Danke! Läuft!!
Ja wie jetzt?
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.
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.