Wieso funktioniert dieser Code? (LED-Blinker)

OP #239242
Lesenswert?
• ▲
▼
Hi Leutz,

bin grad dabei mich ein wenig mit C zu beschäftigen. Als erstes
"Projekt" hab ich einen Wechselblinker angegriffen. Also zwei Led's
die abwechselnd blinken. Der Code:
1
int main(void)
2
{int i, n = 40;
3
DDRB = 0b00001100;
4
PORTB = 0x00;
5
while (1)
6
{
7
PORTB ^= 0b00000100;       // EX-OR
8
for (i=0; i<n; i++){
9
  _delay_ms(25);
10
  }
11
PORTB ^= 0b00001000;       // EX-OR
12
}
13
}

Das funktioniert auch, nur warum? Beim zweiten EX-OR springt der doch
sofort nach der Anweisung zurück zur Zeile mit dem ersten EX-OR, oder?
Also müßte nach dem zweiten EX-OR gar keine Verzögerung mehr zu sehen
sein...?!?

Markus
Gast
Lesenswert?
• ▲
▼
Hihi, das ist ja mal ein lustiger "logischer" Fehler...

Wir nehmen mal an, wir sind in der Delay-Schleife. Dann passiert
folgendes:

  1.) Delay, lange Pause

  2.) PORTB ^= 0b00001000;   /* Die zweiteLED wird umgeschaltet, es
                                leuchten nun beide LEDs oder keine */

  3.) Ende der while(1)-Schleife und Rücksprung an den Anfang
      der while(1)-Schleife. Es ist nur sehr wenig Zeit vergangen.

  4.) PORTB ^= 0b00000100;  /* Die erste LED wird umgeschaltet, es
                               leuchtet wieder nur eine LED */

  5.) Delay-Schleife, lange Pause.

  6.) Wieder bei Schritt 2 weiter....


Der Fehler ist, dass die beiden Schreibzugriffe auf den Port nicht
untereinander stehen. Die Port-Zugriffe schalten die LED ja nicht an
oder aus, sondern schalten sie um.

Prinzipiell ist die Stelle, an der der Rücksprung der While-Schleife
erfolgt egal. Wichtig ist nur die Anordnung:

   - LED 1 umschalten
   - LED 2 umschlaten
   - Pause machen

Wo nun die Wiederholung der While-Schleife passiert ist egal.

Also, ein sehr "lustiger Fehler"...
OP
Lesenswert?
• ▲
▼
Also so richtig kann ich euch nicht folgen...

@Joachim: Dann wäre es ja kein Wechselblinker mehr. Die LED's würden
dann gleichzeitig an oder aus sein.

[ZITAT]
Prinzipiell ist die Stelle, an der der Rücksprung der While-Schleife
erfolgt egal. Wichtig ist nur die Anordnung:

   - LED 1 umschalten
   - LED 2 umschlaten
   - Pause machen
[/ZITAT]
Rein logisch würde das ja bedeuten LED1 würde sofort bei der zweiten
EX-OR Funktion wieder umgeschalten ohne Verzögerung, oder?!?
Oder wird einem PORTB ^= 0b00001000 nur daß gesetzte vierte Bit
"getoogled"???
Gast
Lesenswert?
• ▲
▼
Ganz am Anfang steht die Zeile DDRB=0x00001100. Im ersten Moment sind
also beide LED eingeschaltet. Einige Mikrosekunden später folgt in der
Schleife das erste XOR, welches eine der LED wieder ausknipst - es
leuchtet nur eine LED.

Es folgt die Verzögerung, dann das zweite XOR. Dieses knipst die zweite
LED aus - beide sind also dunkel. Nur wenige Mikrosekunden später
erreichen wir durch die Schleife wieder das erste XOR, das die erste
LED wieder anknipst, wieder leuchtet nur eine LED.

Erneut die Verzögerung, dann das zweite XOR, beide LED leuchten - aber
nur ein paar µs, denn wir erreichen wieder das erste XOR, das LED
Nummer 1 wieder ausschaltet.

Ein wirklicher Wechselblinker ist das nicht, schließlich sind die LED
manchmal beide an oder aus. Die Zeiträume, in denen das der Fall ist,
sind aber so kurz, das man das optisch nicht mehr wahrnimmt.

Eine elegante und pfiffige Lösung, finde ich - aber nicht wirklich
perfekt. Ich schlage vor, das ganze ein wenig anders zu formulieren:
1
DDRB=0x00001000;
2

3
while(1)
4
{
5
   PORTB ^= 0b00001100;
6
   for (i=0; i<n; i++) _delay_ms(25);
7
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 21 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.