Forum: Mikrocontroller und Digitale Elektronik C-Mysterium beim ATMega16


von Jörg Günzel (Gast)


Lesenswert?

Hallo,
mir ist etwas widerfahren, was ich mir beim besten Willen nicht
erklären kann. Ich programmiere den ATMega16 in avr-gcc. Einige
Zählvaraiablen (long int), die vorher mit i, k, usw. benannt waren,
habe ich umbenannt in Count1, Count2, ... um die Aussagekraft zu
erhöhen. Dabei ist mir ein Ersetzungsfehler unterlaufen:

...
for (Count1=0;Count1<6;Count1++)
{
  LED[Count1] anmachen
  // Verzögerungsschleife
  for (Count2=0;Count2<15000;Count2++)
   {
        Delay++;
   }
  LED[Count1] ausmachen
}
...
while(1)
{
  ...
  for (Count1=0;Count2<15000;Count2++)
  ...
}

Vor der Endlosschleife wird eine Kaskade von 6 LEDs über ein
Schieberegister einmal von links nach rechts  zum Aufleuchten gebracht.
In der for-Schleife der Endlosschleife müsste richtigerweise
'Count2=0' statt 'Count1=0' stehen. Das wirkt sich in der
fehlerhaften Version so aus, dass der Aufleuchte-Vorgang der LEDs, der
vor der Endlosschleife steht, dann dreimal so lang dauert.
Wie kann es sein, dass ein logischer Fehler in einem sequentiellen
Programm sich auf eine vorher abgearbeitete Anweisung auswirkt?
Verletzt das nicht das Kausalitätsprinzip? Hat irgendjemand eine Idee?
Gruß Jörg

von A.K. (Gast)


Lesenswert?

Ich vermute, dass Du nur den Optimizer strapazierst. Denn wenn
"Count2" und "Delay" nicht als "volatile" deklariert sind, dann
ist
  for (Count2=0;Count2<15000;Count2++)
   {
        Delay++;
   }
aus Sicht des Compilers funktionell identisch mit
   Count2 = 15000;
   Delay += 15000;
und je nach Kontext, Laune und Wasserstand kann es sein, dass der
Compiler das mal wegoptimiert, mal nicht.

Daher: Delay-Funktion der Library verwenden.

von Marius Schmidt (Gast)


Lesenswert?

Wenn man jetzt noch wüsste wie die heißt ^^

Ich weiss es zB nicht und wäre davon ausgegangen das man einen timer
benutzen muss für sowas...

von A.K. (Gast)


Lesenswert?

Siehe Doku der avr-libc, unter "Busy-wait delay loops".
Oder <avr/delay.h>

Timer nur nötig, wenn man zwischendurch besseres zu tun hat als einfach
nur Schleifchen zu drehen.

von jupp (Gast)


Lesenswert?

Hi,

was macht denn das "Delay++;"?
müsste dort nicht Count2++; stehen?


cu

von David W. (Gast)


Lesenswert?

Nö, das steht ja in der for-Schleifen-Bedingung
for (Count2=0;Count2<15000;>>>Count2++<<<)
Startwert; Endwert; Erhöhung, wenn überhaupt

von jupp (Gast)


Lesenswert?

Ok! Überzeugt.
Aber was macht denn das Delay++; ??

von Jörg Günzel (Gast)


Lesenswert?

@jupp
Das Delay++ war dafür gedacht, dass die Schleife nicht wegoptimiert
wird,  obwohl die Gefahr lt. A.K. ja trotzdem besteht.

@alle
Das scheint mir aber bei mir nicht der Fall zu sein. Denn der von mir
oben beschriebene schnellere Fall, zeigt die LEDs immer noch deutlich
länger als wenn nur die beiden Befehle:

   Count2 = 15000;
   Delay += 15000;

statt der Schleife ausgeführt werden.

Was höchstens sein könnte ist, dass beim schnelleren Fall die Schleife
zu:
for (Count2=0;Count2<15000;Count2++)
   {

   }
Delay+= 15000;

teiloptimiert wird
und im langsamen Fall unverändert als

for (Count2=0;Count2<15000;Count2++)
   {
        Delay++;
   }

ausgeführt wird.

Die *.lst scheint mir die Assemblerdatei zu sein, die man diesbezüglich
untersuchen sollte, oder?
Gruß
   Jörg

von A.K. (Gast)


Lesenswert?

"Die *.lst scheint mir die Assemblerdatei zu sein, die man
diesbezüglich untersuchen sollte, oder?"

Ja.

Generell empfiehlt sich aber, erkennbar sinnlosen Code entweder ganz zu
vermeiden, oder dem Compiler unter Verwendung von "volatile" die
Optimierung abzugewöhnen. Alles andere ist ausgesprochen fragil.

von Jörg Günzel (Gast)


Lesenswert?

In der lst-Datei finde ich die Zeile

ldi r24,lo8(14999)

Ich konnte dieses 'lo8' (und auch 'hi8', das auch vorkommt) weder
im Datenblatt des ATMega, noch im 'Instruction Set' von Atmel noch in
'io.h' oder 'iom16.h'. Kannst Du mir vielleicht sagen, was deren
Bedeutung ist und wo ich hätte suchen müssen?
Gruß Jörg

von Jörg Günzel (Gast)


Lesenswert?

Hallo
das soll jetzt nicht in eine Assembler-Fragestunde ausarten, aber auf
Seite 120 des Atmel-Instruction-Set steht für den Befehl 'SBIW', dass
dort zwingend immer ein Register-Paar übergeben werden muss, als
Beispiel ist dort 'sbiw r25:r24,1' angegeben. In meinem lst-File
taucht aber die Zeile
 sbiw r24,1
auf. Widerspricht dies nicht den obigen Angaben?
Gruß Jörg

von Läubi (Gast)


Lesenswert?

nein es wird einfach Rd udn Rd-1 genommen (mein ich steht auch so im
InstructionSet) ist sozusagen "optional"

von A.K. (Gast)


Lesenswert?

Herrje, lo8 und hi8 sind doch ziemlich offensichtlich die unteren 8 Bits
und die oberen 8 Bits eines 16-Bit Wertes.

von Jörg Günzel (Gast)


Lesenswert?

Ja,
das ist mir dann auch aufgefallen. Trotzdem sollte diese Syntax doch in
irgendeinem Manual erklärt sein oder woher soll man von ihrer Existenz
wissen, wenn man sie nicht gerade aus bestehendem Code herausliest.
Zwar sind "+" oder "-" auch nicht erklärt, aber lo8 und hi8 haben
auch nicht diese Allgemeingültigkeit.
In einem DSP-Assembler-Dialekt mit dem ich auch mal gearbeitet habe,
gab es lo8 jedenfalls nicht.
Gruß Jörg

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.