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
intmain(void)
2
{inti,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
Hallo Markus,
die beiden LEDs werden getrennt umgeschaltet. Wie Du richtig
feststellst, gibt es keine Pause nach dem 2. EX-OR.
Man könnte das zweite EX-OR streichen und stattdessen mit dem 1. EX-OR
beide LEDs gemeinsam umschalten:
PORTB ^= 0b00001100;
Gruß
Joachim
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"...
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"???
Hi
genau so ist das. PORTB ^= 0b00001000 togglet das Bit3, PORTB ^=
0b00000100 das Bit 2. Damit sollte dann die Funktion des
Wechselblinkers klar sein. Wichtig ist natürlich der Ausgangszustand
von PortB. Sind die zwei Bits nicht gleich vor eintritt in die Schleife
ist es kein Wechselblinker mehr.
Matthias
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:
@Olaf:
Danke nochmal für deine Ausführungen, jetzt hab ich's auf alle Fälle
gefressen. Deine Lösung ist, denke ich, programmiertechnisch die beste.
Das äußert sich für mich daran, das sie sofort durchschaubar ist wie sie
funktioniert.
Gruß, Markus
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.