Hallo, ich habe bis gestern gedacht, ich kann mal schnell nebenbei ein Lauflicht programmieren. Doch leider wurde mir nach längerer Fehlersuche eines besseren belehrt. Das Licht sollte einfach nur nach rechts laufen. Das tut es auch mehr oder weniger, aber jeden LED blinkt nur kurz auf statt für 1sec zu leuchten. Das lustige an der Sach ist aber wenn ich über ledra oder ledla alle LEDs blinken lasse bzw. aktivieren Funktioniert es. Kann mir bitte jemand helfen? Ich finden den Fehler leider nicht. AVR Atmega8 Internen Quarz AVR Studio 6 LEDS über BC639 an: PB6 PB7 PD5 PD6 PD7 PB0 das wäre der Sourcecode: ------------------------------------------------------------------------ --- #include <avr/io.h> #include <util/delay.h> #define F_CPU 1000000 unsigned char ledl1 = 0; unsigned char ledl2 = 0; unsigned char ledl3 = 0; unsigned char ledr1 = 0; unsigned char ledr2 = 0; unsigned char ledr3 = 0; unsigned char ledla = 0; unsigned char ledra = 0; void ausgabe(void) { if (ledl1 == 1) { PORTB = PORTB | (1<<PD0); } else { PORTB = PORTB &~ (1<<PB0); } if (ledl2 == 1) { PORTD = PORTD | (1<<PD7); } else { PORTD = PORTD &~ (1<<PD7); } if (ledl3 == 1) { PORTD = PORTD | (1<<PD6); } else { PORTD = PORTD &~ (1<<PD6); } if (ledr1 == 1) { PORTD = PORTD | (1<<PD5); } else { PORTD= PORTD &~ (1<<PD5); } if (ledr2 == 1) { PORTB = PORTB | (1<<PB7); } else { PORTB = PORTB &~ (1<<PB7); } if (ledr3 == 1) { PORTB = PORTB | (1<<PB6); } else { PORTB = PORTB &~ (1<<PB6); } if (ledla == 1) { PORTB = PORTB | (1<<PB0); PORTD = PORTD | (1<<PD7); PORTD = PORTD | (1<<PD6); } else { PORTB = PORTB &~ (1<<PB0); PORTD = PORTD &~ (1<<PD7); PORTD = PORTD &~ (1<<PD6); } if (ledra == 1) { PORTD = PORTD | (1<<PD5); PORTB = PORTB | (1<<PB7); PORTB = PORTB | (1<<PB6); } else { PORTD = PORTD &~ (1<<PD5); PORTB = PORTB &~ (1<<PB7); PORTB = PORTB &~ (1<<PB6); } } int main(void) { DDRB = DDRB | (1<<PB0)| (1<<PB6)| (1<<PB7); // Ausgänge DDRD = DDRD | (1<<PD5)| (1<<PD6)| (1<<PD7); // Ausgänge PORTD = 0x1F; //Pullups für Eingänge aktiviren while(1 == 1) { ledl1=0; ledl2=0; ledl3=0; ledr1=0; ledr2=0; ledr3=0; ausgabe(); _delay_ms(1000); ledl1=0; ledl2=1; ledl3=0; ledr1=0; ledr2=0; ledr3=0; ausgabe(); _delay_ms(1000); ledl1=0; ledl2=0; ledl3=1; ledr1=0; ledr2=0; ledr3=0; ausgabe(); _delay_ms(1000); ledl1=0; ledl2=0; ledl3=0; ledr1=1; ledr2=0; ledr3=0; ausgabe(); _delay_ms(1000); ledl1=0; ledl2=0; ledl3=0; ledr1=0; ledr2=1; ledr3=0; ausgabe(); _delay_ms(1000); ledl1=0; ledl2=0; ledl3=0; ledr1=0; ledr2=0; ledr3=1; ausgabe(); _delay_ms(1000); } } ------------------------------------------------------------------------ -- Besten Dank! PS: Ich würde fast darauf wetten, dass es ein peinlicher Fehler ist :-)
Rolf Schmidt schrieb: > PS: Ich würde fast darauf wetten, dass es ein peinlicher Fehler ist :-) Das glaube ich auch, so macht doch kein Mensch ein Lauflicht! Schau Dir mal die logischen Operationen wie Bitshift an. Alternativ auch die Multiplikation/Division mit/durch 2.
Wie ist deine Optimierung eingestellt? Ich sehe keinen Fehler. Beschreib mal dein Blitzen! Welche IDE? Ingo
Reihenfolge
1 | #include <util/delay.h> |
2 | #define F_CPU 1000000
|
falsch ;( hans
Wow. Das ist das komplizierteste Lauflicht, an das mich erinnern kann. Und das will in diesem Forum was heißen.
:
Wiederhergestellt durch User
Schmeiß den Code weg und fang von vorne an. Vorher aber bitte in einem Buch über den shift-operator lesen... Alle LEDs an einen PORT, dann ist das ein 3-Zeiler.
hans schrieb: > Reihenfolge#include <util/delay.h> > #define F_CPU 1000000 > falsch ;( > > hans Richtig, hatte ich überlesen (Bei dem riesen Code). Aber wenn der interne Oszillator läuft (8Mhz oder 1MHz), dann sollte die 1s halt etwas länger sein. Ingo
Karl Heinz Buchegger schrieb: > Wow. > Das ist das komplizierteste Lauflicht, an das mich erinnern kann. > Und das will in diesem Forum was heißen. Aber .... Ingo hat Recht. Einen offensichtlichen Fehler gibt es nicht.
Dämlichster (Troll-)Fehler wo gibt!!! Bei ausgabe() schaltest Du deine Wunsch-Led ein und unten bei der letzten if-clause setzt Du beide Ports wieder auf aus. Ausnahme: Es werden alle LEDs ein- oder ausgeschaltet. Ab in die Ecke und schämen!!!
debugger schrieb: > Dämlichster (Troll-)Fehler wo gibt!!! > > Bei ausgabe() schaltest Du deine Wunsch-Led ein und unten bei der > letzten if-clause setzt Du beide Ports wieder auf aus. Ausnahme: Es > werden alle LEDs ein- oder ausgeschaltet. <Hand an die Strin klatsch> > > Ab in die Ecke und schämen!!! Richtig. Nämlich: wir Helfer.
Klar kenn ich die shift-operatoren. Wenn man sich den Code an sieht, dann sieht man auch, dass ich ihn zum setzten der Ausgänge nehme :-) Er ist aber wegen Zusatzfunktionen (nicht online) leider ungeeignet. Und wenn die Hardware schon fertig ist, kann man nicht einfach irgendwelche Pins tauschen :-) Aber ich hatte recht, es war ein sehr peinlicher und einfacher Fehler. X+2 Augen sind halt immer besser als nur zwei :-) Danke für den Hinweis
Du könntest doch wenigstens die ganzen (unsigned char) durch eine einzige ersetzen, bei der jedes Bit für eine LED steht. Dann brauchst Du im Hauptprogramm auch nicht (gefühlte) 500 Schreibzugriffe, sondern nur:
1 | unsigned char value; |
2 | while (1) { |
3 | value=0b000001; |
4 | do { |
5 | ausgabe(); |
6 | _delay_ms(1000); |
7 | value=value<<1; |
8 | }
|
9 | while (value<=0b100000); |
10 | }
|
Nur so als Denkanstoß. Wie die ausgabe() Funktion umgeschrieben werden muss, kannst Du Dir sicher selbst denken.
das muss ich natürlich zugeben, diese Variante ist bedeutent schöner programmiert als meine "quick and dirty" Version.
Bei der langen Tipparbeit und Fehlersuche, ist das wohl kaum als "quick" zu bezeichnen...
R. Schmidt schrieb: > Und wenn die Hardware schon fertig ist, kann man nicht einfach > irgendwelche Pins tauschen :-) Das ist richtig. Aber man kann sich zb in einem, nein 2, Arrays die jeweils an den ports auszugebenden Werte ablegen und dann ganz einfach in ausgabe() in die Arrays indizieren um den Wert zu erfahren, der ausgegeben werden soll. Dann spart man sich einen Großteil dieser if - else kette
R. Schmidt schrieb: > mal schnell nebenbei ein > Lauflicht programmieren. Gratuliere. Dein Code hat es in meine All-Time "so-macht-man-es-nicht" Sammlung geschafft...
Bart schrieb: > Bei der langen Tipparbeit und Fehlersuche, ist das wohl kaum als "quick" > zu bezeichnen... Dafür dirty!
Also ich finde den Code toll. Den hebe ich mir auf und erschrecke damit kleine Kinder.
Checker Bunny schrieb: > Den hebe ich mir auf Das wäre doch was zur Abschreckung neugieriger Kollegen? Das muss auch in die Schreibunterlage mit rein!
Ich bin zwar auch Anfänger, aber da musste auch ich schlucken. Kompliziert. Wie es der Zufall so will, habe ich vor 2 Tagen auch ein Lauflicht gemacht. Mein Code ist extrem simpel da er erstmal zum testen war, man kann noch etwas optimieren. Das ganze läuft auf einem Attiny 44 mit internem Takt. Das einzigste was Du tun musste ist die Pinausgänge festlegen und Pinnamen entsprechend Deines Avr ändern. #include <avr/io.h> #include <util/delay.h> int main(void) { DDRA = (1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 << PA5) | (1 << PA7); DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2); while(1) { PORTA |= (1 << PA0); _delay_ms(70); PORTA &= ~((1 << PA0)); PORTA |= (1 << PA1); _delay_ms(70); PORTA &= ~((1 << PA1)); PORTA |= (1 << PA2); _delay_ms(70); PORTA &= ~((1 << PA2)); PORTA |= (1 << PA3); _delay_ms(70); PORTA &= ~((1 << PA3)); PORTB |= (1 << PB0); _delay_ms(70); PORTB &= ~((1 << PB0)); PORTB |= (1 << PB1); _delay_ms(70); PORTB &= ~((1 << PB1)); PORTB |= (1 << PB2); _delay_ms(70); PORTB &= ~((1 << PB2)); PORTA |= (1 << PA7); _delay_ms(70); PORTA &= ~((1 << PA7)); PORTA |= (1 << PA5); _delay_ms(70); PORTA &= ~((1 << PA5)); PORTA |= (1 << PA7); _delay_ms(70); PORTA &= ~((1 << PA7)); PORTB |= (1 << PB2); _delay_ms(70); PORTB &= ~((1 << PB2)); PORTB |= (1 << PB1); _delay_ms(70); PORTB &= ~((1 << PB1)); PORTB |= (1 << PB0); _delay_ms(70); PORTB &= ~((1 << PB0)); PORTA |= (1 << PA3); _delay_ms(70); PORTA &= ~((1 << PA3)); PORTA |= (1 << PA2); _delay_ms(70); PORTA &= ~((1 << PA2)); PORTA |= (1 << PA1); _delay_ms(70); PORTA &= ~((1 << PA1)); } } Also wie man sieht geht es auch extrem einfach. Gruß Fred
Achja. Du kannst z.B. einfach einen Vorwiderstand vor die LED bauen. Plus kommt vom Chip und Minus an gemeinsame Masse.
Fred schrieb: > Also wie man sieht geht es auch extrem einfach. Genau:
1 | #include <avr/io.h> |
2 | #include <util/delay.h> |
3 | |
4 | int main(void) |
5 | {
|
6 | DDRA = 0xFF; |
7 | uint16_t i; |
8 | for(;;) |
9 | {
|
10 | for(i=1;i!=(1<<8);i<<=1) |
11 | {
|
12 | PORTA=(uint8_t)i; |
13 | _delay_ms(70); |
14 | }
|
15 | }
|
16 | return 0; //neaver reached |
17 | }
|
SCNR Wie wäre es mit einem Wettbewerb: Wer schreibt das kürzeste Lauflicht?
Das ist mir klar, daß ich das ganze in einer schleife machen kann. Ich wollte halt nur zeigen, daß seines schon extrem umständlich ist. Auch wenn Deines schön klein ist, so finde ich es absolut unübersichtlich. Zum lernen finde ich die Portnamen etc. besser.
troll schrieb: > Wie wäre es mit einem Wettbewerb: Wer schreibt das kürzeste Lauflicht? Ich leg dann mal vor:
1 | #include <avr/io.h> |
2 | #include <util/delay.h> |
3 | main(){DDRA=~0;char i;for(;;)for(i=0,PORTA=1;i<8;i++,PORTA<<=1,_delay_ms(70));} |
Kann sein dass man noch unsigned vor den char setzen muss, hab gerade keinen AVR-GCC zur Hand. Mal sehen, vielleicht schlage ich Karl-Heinz ja dieses Mal...
troll schrieb: > Kann sein dass man noch unsigned vor den char setzen muss Nein Blödsinn, das war für eine andere Version. :-(
Ich sehe schon, wie in so manchen anderen Threads wird hier alles ins lächerliche gezogen. Vielleicht sollte man mal über die Gastfunktion nachdenken.
Fred schrieb: > Ich sehe schon, wie in so manchen anderen Threads wird hier alles ins > lächerliche gezogen. > Vielleicht sollte man mal über die Gastfunktion nachdenken. Ich ziehe überhaupt nichts ins Lächerliche... Sei nicht so humorlos, kurze (und unübersichtliche) Programme in C haben eine lange Tradition. Siehe auch IOCC. :-)
Sorry for x-fach-Post. Ich bessere nochmal nach: Beispiel =~ s!#include <util/delay.h>!! Sollte funktionieren, Defaultwerte passen.
...viel interessanter ist ein Lauflicht mit 10 Duo LED an 5 Portpins mit 5 Widerständen. Mit integriertem weichem Farbwechsel von rot zu grün während das Lauflicht läuft.... TS
Die Ausgabefunktion kann man auch drastisch vereinfachen. Und Parameterübergabe macht man nicht in globalen Variablen, sondern direkt:
1 | #include <avr/io.h> |
2 | #define F_CPU 1e6
|
3 | #include <util/delay.h> |
4 | |
5 | #define LEDL1B (1<<PB0)
|
6 | #define LEDL2D (1<<PD7)
|
7 | #define LEDL3D (1<<PD0)
|
8 | #define LEDR1D (1<<PD5)
|
9 | #define LEDR2B (1<<PB7)
|
10 | #define LEDR3B (1<<PB6)
|
11 | |
12 | void ausgabe( uint8_t val ) |
13 | {
|
14 | uint8_t vald = PORTD & ~(LEDL1B | LEDR2B | LEDR3B); |
15 | uint8_t valb = PORTB & ~(LEDL2D | LEDL3D | LEDR1D); |
16 | if( val & 1<<0 ) |
17 | valb |= LEDL1B; |
18 | if( val & 1<<1 ) |
19 | vald |= LEDL2D; |
20 | if( val & 1<<2 ) |
21 | vald |= LEDL3D; |
22 | if( val & 1<<3 ) |
23 | vald |= LEDR1D; |
24 | if( val & 1<<4 ) |
25 | valb |= LEDR2B; |
26 | if( val & 1<<5 ) |
27 | valb |= LEDR3B; |
28 | PORTD = vald; |
29 | PORTB = valb; |
30 | }
|
31 | |
32 | int main() |
33 | {
|
34 | DDRB = LEDL1B | LEDR2B | LEDR3B; |
35 | DDRD = LEDL2D | LEDL3D | LEDR1D; |
36 | |
37 | for(;;){ |
38 | uint8_t val = 1; |
39 | ausgabe( 0 ); |
40 | do{ |
41 | _delay_ms(1000); |
42 | ausgabe( val ); |
43 | val <<= 1; |
44 | }while( val != 0b1000000 ); |
45 | }
|
46 | }
|
Peter
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.