Wieso geht das nicht ? while(1) { if (licht==1) { for(i=0;i<10000;i++) { PORTB=0b00111000; PORTC=0b00111111; PORTD=0b11100000; _delay_ms(2); } } if (licht==2) { for(i=0;i<10000;i++) { PORTB=0b00111000; PORTC=0b00111111; PORTD=0b11100000; _delay_us(750); PORTB=0b00000000; PORTC=0b00000000; PORTD=0b00000000; _delay_us(250); } } if (licht==3) { for(i=0;i<10000;i++) { PORTB=0b00111000; PORTC=0b00111111; PORTD=0b11100000; _delay_us(500); PORTB=0b00000000; PORTC=0b00000000; PORTD=0b00000000; _delay_us(500); } } if (licht==4) { for(i=0;i<10000;i++) { PORTB=0b00111000; PORTC=0b00111111; PORTD=0b11100000; _delay_us(250); PORTB=0b00000000; PORTC=0b00000000; PORTD=0b00000000; _delay_us(750); } } if (licht==5) { for(i=0;i<10000;i++) { PORTB=0b00000000; PORTC=0b00000000; PORTD=0b00000000; _delay_ms(1); } } if (licht==6) { licht=licht-6; } else if (licht==0) { anderes geblinke } Geschrieben auf einem Atmega8 Unten befindet sich eine interrupt routine welche den wert licht+1 macht wenn der Taster gedrückt wird eigentlich sollte jetzt ja das Lich zuerst Hell und nach jedem Druck immer Dunkler werden Danke schonmal im voraus martaniu
- Taste nicht entprellt? - Variable licht falsch initialisiert? - Fall licht > 6 Fall nicht bearbeitet(der ja nicht auftreten sollte, aber ja vielleicht doch auftritt.
Ich D. schrieb: > if (licht==6) > { > licht=licht-6; > } licht = 0 Ich D. schrieb: > if (licht==6) > { > licht=licht-6; > } > else if (licht==0) > { > anderes geblinke > } Wenn licht auf 0 gesetzt wurde (also vorher 6 war) dann kommt man natürlich, im selben durchlauf, nicht in den else zweig.
Ich D. schrieb: > Wieso geht das nicht ? Tolle Frage. Was geht nicht? Natürlich geht das. Es kommt nur nicht das raus, was du erwartest, oder? Du wirst uns schon erzählen müssen, was das ist, was du erwartest.
Was genau heisst: "Funktioniert nicht"? Siehe: https://www.mikrocontroller.net/articles/Netiquette Wenn man Deinen Code ansieht, so hängt einzig die Dauer der Verzögerung von dem Wert der Variablen licht ab. licht delay 1 2ms 2 750us 3 500us 4 250us 5 1ms ... Alle anderen von der Bedingung abhängigen Vorgänge sind unabhängig vom Wert der Variablen licht gleich. Daher ist es zu überlegen, ob Du nicht eine einzige Funktion schreibst, die ausschliesslich ein delay je nach ihrem Parameter ausführt. Das macht das Programm übersichtlicher. Dazu kannst Du wieder eine Kette von if-Anweisungen benutzen oder eine switch-Anweisung. z.B. so
1 | void PerformDelay (int i) { |
2 | if (licht==1) |
3 | _delay_ms(750); |
4 | else if (licht==2) |
5 | _delay_ys(1); |
6 | else if (licht==3) |
7 | _delay_ms(500); |
8 | else if (licht==4) |
9 | _delay_ms(250); |
10 | else if (licht==5) |
11 | _delay_ms(1); |
12 | |
13 | // ...
|
14 | else
|
15 | // ...
|
16 | }
|
Das ist eigentlich auch nur dann nötig, falls Du das delay das mit dem GCC für AVR kommt verwendest, weil dort das delay keine Variable als Parameter akzeptiert. Aber wir wissen ja auch nicht welcher uC oder welcher Compiler. Siehe https://www.mikrocontroller.net/articles/Netiquette Lediglich die Benennung der Ports deutet darauf hin, dass es sich um einen AVR handeln könnte . Das man Tasten wegen ihres Prellens nicht in Interrupt-Funktionen auswertet ist ja schon erwähnt worden.
Ooops. Die Bedingungen müssen natürlich nicht: if (licht==1) sein, sondern if (i == 1) was mich veranlasst, darauf hinzuweisen, das man für Variablennamen möglichst aussagekräftige verwendet. In diesem Sinne ist "licht" unzureichend - aber auch "i".
Noch ein Ooops. Sorry. Natürlich unterscheiden sich die abhängigen Anweisungen in noch mehr Punkten. Ich habe das - offen gesagt - ersteinmal aus Lässigkeit ignoriert. Dann schien es mir wahrscheinlicher, dass es sich um ein Versehen handelt. Aber das muss natürlich nicht zutreffen.
Mein grosses V. schrieb: > Ich D. schrieb: >> Wieso geht das nicht ? > > Tolle Frage. Was geht nicht? Natürlich geht das. Es kommt nur nicht das > raus, was du erwartest, oder? > > Du wirst uns schon erzählen müssen, was das ist, was du erwartest. Ich wollte das wenn ich das erste mal den Taster drücke sich der komplette Würfel auf 100% Helligkeit anschaltet und beim 2.ten mal drücken auf 75% dimmt usw. am Ende soll er aus sein und nach nochmal drücken wieder in die Else-schleife springen. Den Taster kann man benutzen da er Pull-up widerstände hat und auch in der Interroupt ein delay von 100ms ist.
Jetzt geht es halbwegs... Wenn ich am anfang meine variable (geändert auf g) auf 1 setze leuchtet der Würfel und das Dimmen funktioniert, wenn ich allerdings einmal durch bin mit dem Dimmen läuft der Rest einfach durch ohne das ich wieder Dimmen kann.
1 | if ( licht == ... ) |
2 | {
|
3 | for(i=0;i<10000;i++) |
4 | {
|
5 | ...
|
6 | _delay_ms(1); |
7 | }
|
8 | }
|
9 | ...
|
Das Problem deines Programmes ist das delay mit zehn Sekunden. Nur danach wird die Varaible Licht neu ausgewertet, selbst wenn diese durch irgendwas (Interrupt) mittlerweile mehrfach verändert wurde. Du solltest das gesamte Konzept des Programmes umstellen. Offensichtlich willst Du verschiedene Bitmuster getimt an Ports ausgeben. Das kleinste Delay welches ich gesehen habe, ist 250µs. ALso baue einen Timertick mit 250µs und schalte dort geeignet um. Das hier macht noch nicht exakt was du wahrscheinlich willst, aber es sollte an Anreiz gehen:
1 | uint_xx_t WAIT[] = ( ... , ... , ... , ... ); |
2 | uint_xx_t TimeTick = 0; |
3 | uint8_t State = 0; |
4 | |
5 | main ( void ) |
6 | {
|
7 | // init Timer ------------------------------
|
8 | ...
|
9 | //-- Main ----------------------------------
|
10 | while ( 1 ) |
11 | {
|
12 | asm volatile ( "nop" ); |
13 | }
|
14 | }
|
15 | |
16 | ISR ( TIMER_x_OVF ) // alle 250µs |
17 | {
|
18 | //-- Variable Licht betüdeln ---------------
|
19 | uint_xx_t Max = (uint_xx_t) ( sizeof(WAIT) / sizeof(WAIT[0]) ) |
20 | |
21 | if ( ... ) Licht = 1; |
22 | else if ( ... ) Licht = 2; |
23 | ...
|
24 | if ( Licht >= Max ) Licht = 0; |
25 | |
26 | // Timing erzeugen -------------------------
|
27 | if ( ++TimeTick < WAIT[ Licht ] ) return; |
28 | TimeTick = 0; |
29 | |
30 | // Ausgänge erzeugen -----------------------
|
31 | switch ( State ) |
32 | {
|
33 | case 0: |
34 | {
|
35 | PORTB=0b00111000; |
36 | PORTC=0b00111111; |
37 | PORTD=0b11100000; |
38 | State = 1; |
39 | break; |
40 | }
|
41 | case 1: |
42 | {
|
43 | PORTB=0b00000000; |
44 | PORTC=0b00000000; |
45 | PORTD=0b00000000; |
46 | State = 0; |
47 | break; |
48 | }
|
49 | default:
|
50 | State = 0; |
51 | }
|
52 | //-- fertig --------------------------------
|
53 | }
|
Ich D. schrieb: > in > der Interroupt ein delay von 100ms ist. very bad idea. 1. Versuche herauszufinden warum. 2. Bemühe dich, verständliche Grammatik anzuwenden.
Ich D. schrieb: > Den Taster kann man benutzen da er Pull-up widerstände hat und auch in > der Interroupt ein delay von 100ms ist. Immerhin hast du 'widerstände' nicht mir 'ie' geschrieben. Das ist aber auch schon das einzig Gute. Pull-Ups haben mit Entprellung gar nichts zu tun und ein Delay in der ISR ist nur in ganz wenigen Ausnahmefällen eine gute Idee. Bei einer nicht funktionierenden Entprellung ist es das allerdings nicht. Einen Timer brauchst du sowieso. Damit und nur damit, kannst du das Entprellen gleich mit erledigen.
Ich entschuldige mich für meine Rechtschreibung ^^ bin noch in der Schule und nicht so häufig in Foren unterwegs. Die Delays habe ich jetzt aus den if-schleifen genommen und es geht immmer noch so halbwegs Trottdem vielen Dank dafür das ihr mir schonmal soweit geholfen habt. martaniu
Ich D. schrieb: > wenn ich allerdings einmal durch > bin mit dem Dimmen läuft der Rest einfach durch ohne das ich wieder > Dimmen kann. dann versuch mal die Antwort von Kaj zu lesen
Ich D. schrieb: > Ich entschuldige mich für meine Rechtschreibung ^^ bin noch in der > Schule und nicht so häufig in Foren unterwegs. > Die Delays habe ich jetzt aus den if-schleifen genommen und es geht > immmer noch so halbwegs Trottdem vielen Dank dafür das ihr mir schonmal > soweit geholfen habt. > martaniu Nun, wenn Du Schüler bist, dann bist Du vermutlich auch ziemlicher Anfänger. Das waren wir alle mal - und viele haben solchen Code geschrieben wie Du. Du sagst das es so halbwegs geht: Es wäre aber vermutlich doch nützlich und würde Deine Note verbessern, wenn Du uns den kompletten Code hier postest und die Kritiken dazu liest und den Code weiter verbesserst. Ich weiß, Kritik ist nicht nur angenehm und manchmal ist der Ton hier sehr rau. Aber es wäre auch nützlich, wenn es Dir gelänge, das möglichst zu ignorieren. Kritisch finde ich, die Verwendung von Interrupts zur Tastenbehandlung und vor allem die Verwendung von Verzögerungen in Interrupts. Letzteres ist für einen Anfänger unter allen Umständen zu vermeiden. Ersteres kann man mit Erfahrung - wenn man es zwangsweise tun MUSS - irgendwie hinkriegen. Aber der Profi vermeidet das, wie Senf auf der Kirschtorte. Eine der Hauptschwierigkeiten für Anfänger besteht darin, sich den tatsächlichen Ablauf ihres Programms irgendwie vorzustellen. Das zu lernen und zu üben, ist ein Problem vor dem jeder mal steht. Das kann man mit verschiedenen Methoden angehen, von denen Du die für Dich beste erst einmal herausfinden musst. Ich schlage Dir vor, dass Du Dir einen Zeitstrahl auf einem grossen Papier hin zeichnest. Ignoriere im ersten Schritt die Interrupts. Schreibe wirkliche Zeiten an den Strahl. Eine sinnvolle Aufteilung hängt von der Taktfrequenz ab. Bei 1MHz sind das etwa 1 bis 5us. Du musst nicht jeden Befehl hinschreiben, aber doch die für die Funktion wesentlichen Befehle. Darunter die Verzögerung. Dann guck Dir den Interrupt an. Nimm den erst einmal als alleinstehenden Code als wenn es den anderen nicht gäbe. Nimm den selben Zeitmaßstab wie in der vorherigen Zeichnung. Nimm am besten einen zweiten Bogen Papier dazu. Wenn Du das fertig hast, dann lege das Papier mit dem Interrupt mal an die Zeitlinie des Hauptprogramms. Wann kann der Interrupt auftreten? Vermutlich immer; stimmt es? Was hat es für Folgen, wenn der Interrupt kurz vor oder während der Verzögerungen auftritt? Wann werden Variablenänderungen im Interrupt für das Hauptprogramm wirksam? Zu der Entprellung lies mal hier: https://www.mikrocontroller.net/articles/Entprellung Viel Erfolg.
So sieht mein Code bislang aus. Die idee des Dimmens ist ganz oben. Hab jetzt die For-schleife rausgenommen mit den 10 sek. und die Variable verändert. Danke für eure hilfe martaniu -- Über dem Texteingabefeld steht folgendes: Wichtige Regeln - erst lesen, dann posten! Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang -rufus
:
Bearbeitet durch User
Ich D. schrieb: > So sieht mein Code bislang aus. Ach du Sch....öner Kot. Das ist Spaghetti vom Feinsten.
Hab den Fehler gefunden :/ Ich kann aus der for-schleife nicht in die if-schleife springen aus der else-if raus. Wenn ihr Ideen habt was ich verändern kann immer her damit. Schonmal im voraus danke. Martaniu
Ich D. schrieb: > Ich kann aus der for-schleife nicht in die if-schleife springen ... http://www.if-schleife.de
Frank M. schrieb: > Ich D. schrieb: >> Ich kann aus der for-schleife nicht in die if-schleife springen ... > > http://www.if-schleife.de ?
Ein paar Anmerkungen : 1. du definierst die variable b einmal global und einmal lokal in der ISR. Mit sowas legt man sich schnell aufs Kreuz. Schalte mal ein paar compiler warnings scharf und versuche den code sauber zu kriegen. 2. globale Variablen, die von ISRs modifiziert werden, solltest du immer volatile deklarieren. Ohne volatile optimiert der Compiler eventuell die Zugriffe auf eine vermeintlich nutzlose Variable weg.
immer her damit. Indem Du Dir meine Antwort (ziemlich weit oben) mal durchliest und es so umsetzt..
Vor allem ist das eigentlich ein Paradebeispiel, welches mit einer Switch <> Case Anweisung zu machen ist.
Ich würde generell jedem Programmierer empfehlen, sich mal die Clean Code Konzepte zu Gemüte zu führen (google ist dein Freund). Wer diese auch nur ein bisschen befolgt, macht es der Gemeinde hier sehr viel einfacher, seinen code zu verstehen und zu beurteilen.
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.