Hallo Leute!! Habe folgendes Problem: möchte mit einem Taster ein lauflicht starten und dann wieder unterbrechen bzw. die drei leds die als Lauflicht (beim ersten betätigen des Tasters)an sind mit dem zweite betätigen des Tasters ausmachen. Bist zum an machen des Lauflichtes mit LED funktioniert mein code, jedoch das ausmachen nicht. Wo ist der fehler ? Bzw. wie sag ich dem Controller das der taster zum zweiten mal gedrückt wurde? #include <mega8.h> #include <delay.h> #include <stdint.h> void main (void) { uint8_t pPortB,test; pPortB = PINB.0; pPortB+=2; test=pPortB; DDRD = 0xFF; // PORTD als Ausgang PORTD = 0xFF; //PORTD auf high (5V) DDRB = 0x00; // PORTB als Eingang PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0 while (1) { if (PINB.0 == 0) { while (1){ PORTD.0=0; delay_ms (10); PORTD.0=1; delay_ms (50); PORTD.1=0; delay_ms (10); PORTD.1=1; delay_ms (50); PORTD.2=0; delay_ms (10); PORTD.2=1; delay_ms (50); } } else { PORTD.0 = 1; //LED1 aus PORTD.1 = 1; //LED2 aus PORTD.2 = 1; //LED3 aus } if (test == 2); { PORTD.0 = 1; //LED1 PORTD.1 = 1; //LED2 aus PORTD.2 = 1; //LED3 aus break; } } }
Du musst anfangen mal einen vernünftigen Programmierstil zu entwickeln! Dazu gehören vernünftige und konsistente Einrückungen. Auch das Einfügen von exzessiven Leerzeilen-Blöcken trägt nicht wirklich zur Übersicht bei. Im Gegenteil, dadurch daß der Code nur unnötig in die Länge gezogen wird, leidet die Übersicht. Dein Code mal etwas umformatiert
1 | #include <mega8.h> |
2 | #include <delay.h> |
3 | #include <stdint.h> |
4 | |
5 | void main (void) |
6 | {
|
7 | uint8_t pPortB,test; |
8 | |
9 | pPortB = PINB.0; |
10 | pPortB += 2; |
11 | |
12 | test = pPortB; |
13 | |
14 | DDRD = 0xFF; // PORTD als Ausgang |
15 | PORTD = 0xFF; //PORTD auf high (5V) |
16 | DDRB = 0x00; // PORTB als Eingang |
17 | PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0 |
18 | |
19 | while (1) |
20 | {
|
21 | if (PINB.0 == 0) |
22 | {
|
23 | while (1) |
24 | {
|
25 | PORTD.0=0; |
26 | delay_ms (10); |
27 | PORTD.0=1; |
28 | delay_ms (50); |
29 | PORTD.1=0; |
30 | delay_ms (10); |
31 | PORTD.1=1; |
32 | delay_ms (50); |
33 | PORTD.2=0; |
34 | delay_ms (10); |
35 | PORTD.2=1; |
36 | delay_ms (50); |
37 | }
|
38 | }
|
39 | else
|
40 | {
|
41 | PORTD.0 = 1; //LED1 aus |
42 | PORTD.1 = 1; //LED2 aus |
43 | PORTD.2 = 1; //LED3 aus |
44 | }
|
45 | |
46 | if (test == 2) |
47 | ;
|
48 | {
|
49 | PORTD.0 = 1; //LED1 |
50 | PORTD.1 = 1; //LED2 aus |
51 | PORTD.2 = 1; //LED3 aus |
52 | break; |
53 | }
|
54 | }
|
55 | }
|
Und jetzt gehst du mal zu deinem Lauflichtcode und siehst dir die umgebende Kontrollstruktur darin an. Wenn du das tust, dann findest du, dass dieser LED-Blink Code in einer while(1) Schleife eingebettet ist, also einer Endlosschleife. Sobald die Programm- ausführung da drin angelangt ist, kommt sie nie wieder raus. PS: Der Strichpunkt beim Test von test auf 2 war wahrscheinlich so nicht gewollt. Trotzdem ist er drinnen und sorgt so dafür, daß der nachfolgende Programmblock nicht unter Kontrolle des if steht.
hmm leider hab ich immer noch keine ahnung wie ich dem controller mitteilen soll das der taster zum zweiten mal gedrpckt wurde hat einer ein beispiel code oder ne idee?
Vitalij K. wrote: > hmm leider hab ich immer noch keine ahnung wie ich dem controller > mitteilen soll das der taster zum zweiten mal gedrpckt wurde hat einer > ein beispiel code oder ne idee? Das Problem ist das Erkennen eines Tastendrucks. Das ist zunächst mal ziemlich schwierig, weil dir da die Hardware unter Umständen einen Strich durch die Rechnung macht: Taster prellen. D.h. was du als einmaligen Tastendruck empfindest, sieht für den µC so aus als ob der Taster in kurzer Zeit ein paar mal gedrückt und wieder losgelassen wird. Und Entprellen eines Tasters ist, wenn man es gut machen will, gar nicht so einfach. Aber seis drum. Einen Tastendruck erkennt man daran, dass man einen Flankenwechsel erkennen muss. D.h. Der Taster wechselt den Eingansgpegel von 1 auf 0. Und es ist nur diese Änderung die dich interessiert, nicht das der Pegel jetzt dauernd auf 0 ist. Du musst also in einer Variablen den Zustand des Einganspins speichern um im nächsten Schleifendurchlauf erkennen zu können, ob sich der Pegel verändert hat. Probier mal das hier aus
1 | #include <mega8.h> |
2 | #include <delay.h> |
3 | #include <stdint.h> |
4 | |
5 | int main (void) |
6 | {
|
7 | uint8_t TasterJetzt, TasterVorher; |
8 | uint8_t Count; |
9 | |
10 | DDRD = 0xFF; // PORTD als Ausgang |
11 | PORTD = 0xFF; // PORTD auf high (5V) |
12 | DDRB = 0x00; // PORTB als Eingang |
13 | PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0 |
14 | |
15 | TasterVorher = 1; |
16 | Count = 0; |
17 | |
18 | while (1) |
19 | {
|
20 | TasterJetzt = PINB.0; // den jetzigen Zustand des Tasters feststellen |
21 | |
22 | if( TasterJetzt != TasterVorher ) // gibt es einen Unterschied? |
23 | {
|
24 | // Der Unterschied kann jetzt beides bedeuten:
|
25 | // Taster wurde gedrückt oder
|
26 | // Taster wurde losgelassen
|
27 | // Wir sind nur am Fall 'Taster gedrückt' interessiert
|
28 | // Wenn der Taster aber gedrückt wurde, dann muss TasterJetzt
|
29 | // aber den Wert 0 haben
|
30 | |
31 | if( TasterJetzt == 0 ) |
32 | {
|
33 | // mitzählen wie oft die Taste gedrückt wurde
|
34 | Count++; |
35 | |
36 | // Der wievielte Tastendruck war das jetzt?
|
37 | // Der erste? -> Led einschalten
|
38 | // Der zweite? -> Led ausschalten und die Tasterzählung
|
39 | // wieder von vorne beginnen
|
40 | if( Count == 1 ) |
41 | PORTD.0 = 0; |
42 | |
43 | if( Count == 2 ) |
44 | {
|
45 | PORTD.0 = 1; |
46 | Count = 0; |
47 | }
|
48 | }
|
49 | }
|
50 | |
51 | // den jetzigen Zustand des Tasters als den vorhergehenden
|
52 | // merken, damit beim nächsten Abfragen des Tasters damit
|
53 | // verglichen werden kann und ein Wechsel detektiert werden kann
|
54 | TasterVorher = TasterJetzt; |
55 | |
56 | // etwas warten um das Tastenprellproblem etwas zu entschärfen
|
57 | delay_ms (10); |
58 | }
|
59 | }
|
viele dank geht jetzt versuche jetz den code nachzu vollziehen...sonst meld ich mich noch mal bei dir Karl heinz Buchegger
Gut. bedenke immer, ich muss blind programmieren, da ich nicht deinen Compiler habe. Zu deinem Lauflicht: Du musst von der Vorstellung weg, dass du einen Codeblock hast, in dem ständig eine LED nach der anderen ein/aus geschaltet wird. Stattdessen musst du das in der Hauptschleife machen. Dazu benutzt du eine weitere Variable, die dir anzeigt welche LED als nächstes einzuschalten ist. Diese Variable wird dann laufend erhöht. Ungefähr so
1 | ....
|
2 | |
3 | int main( void ) |
4 | {
|
5 | ....
|
6 | uint8_t NextLed; |
7 | ....
|
8 | |
9 | NextLed = 0; |
10 | |
11 | while( 1 ) |
12 | {
|
13 | ....
|
14 | |
15 | // alle LED mal aus
|
16 | PORTD.0 = 1; |
17 | PORTD.1 = 1; |
18 | PORTD.2 = 1; |
19 | |
20 | // welche LED ist als nächstes drann mit einschalten
|
21 | if( NextLed == 0 ) |
22 | PORTD.0 = 0; |
23 | |
24 | else if( NextLed == 1 ) |
25 | PORTD.1 = 0; |
26 | |
27 | else if( NextLed == 2 ) |
28 | PORTD.2 = 0; |
29 | |
30 | // und merken, dass im nächsten Schleifendurchlauf die
|
31 | // nächste Led drannkommt. Aber aufpassen: Nach der
|
32 | // letzten LED muss wieder die erste drann kommen
|
33 | NextLed++; |
34 | if( NextLed == 3 ) |
35 | NextLed = 0; |
36 | |
37 | // etwas warten
|
38 | delay_ms( 10 ); |
39 | }
|
40 | }
|
Und jetzt liegt es an dir, die beiden Teile: Tastendrücke und Lauflicht, miteinander zu verbinden. Ich würde dazu eine weitere Variable benutzen, die mir anzeigt, ob das Lauflicht ein oder ausgeschaltet ist. Der Tastencode setzt diese Variable entsprechend und der Lauflichtcode wird vom Inhalt dieser Variablen abhängig gemacht.
Habe entlich wieder Zeit gefunden meine C-Kenntnisse zu erweitern und an dem Lauflicht zu programmieren. Leider nicht vom Erfolg gekrönt was mach ich falsch hier der code: #include <mega8.h> #include <delay.h> #include <stdint.h> void main (void) { uint8_t TasterJetzt, TasterVorher; uint8_t ZaehlerTaster; uint8_t ZaehlerLED; uint8_t LED1,LED2,LED3; DDRD = 0xFF; // PORTD als Ausgang PORTD = 0xFF; //PORTD auf high (5V) DDRB = 0x00; // PORTB als Eingang PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0 TasterVorher = 1; ZaehlerTaster = 0; ZaehlerLED = 0; LED1 = PORTD.0; LED2 = PORTD.1; LED3 = PORTD.2; while (1) { LED1 = 1; // LED1 (grün) aus LED2 = 1; // LED2 (gelb) aus LED3 = 1; // LED3 (rot) aus TasterJetzt = PINB.0; // den jetzigen Zustand des Tasters feststellen if( TasterJetzt != TasterVorher ) // gibt es einen Unterschied? { // Der Unterschied kann jetzt beides bedeuten: // Taster wurde gedrückt oder // Taster wurde losgelassen // Wir sind nur am Fall 'Taster gedrückt' interessiert // Wenn der Taster aber gedrückt wurde, dann muss TasterJetzt // aber den Wert 0 haben if( TasterJetzt == 0 ) { // mitzählen wie oft die Taste gedrückt wurde ZaehlerTaster++; // Der wievielte Tastendruck war das jetzt? // Der erste? -> Led einschalten // Der zweite? -> Led ausschalten und die Tasterzählung // wieder von vorne beginnen if( ZaehlerTaster == 1 ) if( ZaehlerLED == 0) { LED1 = 0; delay_ms (100); LED1 = 1; } if( ZaehlerLED == 1) { LED2 = 0; delay_ms (100); LED2=1; } if( ZaehlerLED == 2) { LED3 = 0; delay_ms(100); LED3 = 1; ZaehlerLED++; if( ZaehlerLED == 3) { ZaehlerLED = 0; } } if( ZaehlerTaster == 2 ) { PORTD.0 = 1; PORTD.1 = 1; PORTD.2 = 1; ZaehlerTaster = 0; } } } // den jetzigen Zustand des Tasters als den vorhergehenden // merken, damit beim nächsten Abfragen des Tasters damit // verglichen werden kann und ein Wechsel detektiert werden kann TasterVorher = TasterJetzt; // etwas warten um das Tastenprellproblem etwas zu entschärfen delay_ms (10); } }
ABgesehen von so manch anderem Problem, seit wann wird eine LED eingeschaltet, indem man einer unbeteiligten Variablen etwas zuweist
1 | void main (void) |
2 | {
|
3 | ...
|
4 | uint8_t LED1,LED2,LED3; |
5 | |
6 | ....
|
7 | |
8 | LED1 = PORTD.0; |
9 | LED2 = PORTD.1; |
10 | LED3 = PORTD.2; |
11 | |
12 | while (1) |
13 | {
|
14 | LED1 = 1; // LED1 (grün) aus |
15 | LED2 = 1; // LED2 (gelb) aus |
16 | LED3 = 1; // LED3 (rot) aus |
17 | ....
|
Nach der Zuweisung LED1 = PORTD.0; ist LED1 nicht gleichbedeutend mit PORTD.0 LED1 bekommt den Wert von PORTD.0, aber LED1 und PORTD.0 sind auch danach 2 völlig voneinander verschiedene Dinge! Wenn du eine LED ein oder ausschalten willst, dann musst du schon etwas an PORTD.0 zuweisen!
1 | #include <mega8.h> |
2 | #include <delay.h> |
3 | #include <stdint.h> |
4 | |
5 | void main (void) |
6 | {
|
7 | uint8_t TasterJetzt, TasterVorher; |
8 | uint8_t ZaehlerTaster; |
9 | uint8_t Lauflicht; |
10 | uint8_t ZaehlerLED; |
11 | |
12 | DDRD = 0xFF; // PORTD als Ausgang |
13 | PORTD = 0xFF; // PORTD auf high (5V) |
14 | DDRB = 0x00; // PORTB als Eingang |
15 | PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0 |
16 | |
17 | TasterVorher = 1; |
18 | ZaehlerTaster = 0; |
19 | ZaehlerLED = 0; |
20 | Lauflicht = 0; // Lauflicht ist aus |
21 | |
22 | PORTD.0 = 1; |
23 | PORTD.1 = 1; |
24 | PORTD.2 = 1; |
25 | |
26 | while (1) |
27 | {
|
28 | TasterJetzt = PINB.0; // den jetzigen Zustand des Tasters feststellen |
29 | if( TasterJetzt != TasterVorher ) // gibt es einen Unterschied? |
30 | {
|
31 | // Der Unterschied kann jetzt beides bedeuten:
|
32 | // Taster wurde gedrückt oder
|
33 | // Taster wurde losgelassen
|
34 | // Wir sind nur am Fall 'Taster gedrückt' interessiert
|
35 | // Wenn der Taster aber gedrückt wurde, dann muss TasterJetzt
|
36 | // aber den Wert 0 haben
|
37 | |
38 | if( TasterJetzt == 0 ) |
39 | {
|
40 | // mitzählen wie oft die Taste gedrückt wurde
|
41 | ZaehlerTaster++; |
42 | |
43 | if( ZaehlerTaster == 1 ) |
44 | Lauflicht = 1; // erster Tastendruck: Lauflicht ein |
45 | |
46 | if( ZaehlerTaster == 2 ) |
47 | {
|
48 | Lauflicht = 0; // zweiter Tastendruck: Lauflicht aus |
49 | ZaehlerTaster = 0; |
50 | }
|
51 | }
|
52 | }
|
53 | |
54 | TasterVorher = TasterJetzt; |
55 | delay_ms (10); |
56 | |
57 | // was ist mit dem Lauflicht?
|
58 | // gibt es in diesem Durchgang etwas zu tun?
|
59 | if( Lauflicht == 1 ) |
60 | {
|
61 | // mal alle LEDs ausschalten. Die nächste LED wird erst
|
62 | // danach abhängig vom Zähler eingeschaltet
|
63 | PORTD.0 = 1; |
64 | PORTD.1 = 1; |
65 | PORTD.2 = 1; |
66 | |
67 | if( ZaehlerLED == 0) |
68 | PORTD.0 = 0; |
69 | |
70 | else if( ZaehlerLED == 1) |
71 | PORTD.1 = 0; |
72 | |
73 | else if( ZaehlerLED == 2) |
74 | PORTD.2 = 0; |
75 | |
76 | delay_ms(100); |
77 | |
78 | ZaehlerLED++; |
79 | if( ZaehlerLED == 3) |
80 | ZaehlerLED = 0; |
81 | }
|
82 | }
|
83 | }
|
davon ausgehend das der undleserliche code am anfang frei von syntaxfehlern ist versuch folgendes (ist absolut unsauber programmiert!!!) #include <mega8.h> #include <delay.h> #include <stdint.h> void main (void) { uint8_t pPortB,test, hilfsvariable; pPortB = PINB.0; pPortB+=2; test=pPortB; DDRD = 0xFF; // PORTD als Ausgang PORTD = 0xFF; //PORTD auf high (5V) DDRB = 0x00; // PORTB als Eingang PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0 hilfsvariable = 1; while (1) { if (PINB.0 == 0) hilfsvariable = 1; { while (hilfsvariable == 1){ PORTD.0=0; delay_ms (10); PORTD.0=1; delay_ms (50); PORTD.1=0; delay_ms (10); PORTD.1=1; delay_ms (50); PORTD.2=0; delay_ms (10); PORTD.2=1; delay_ms (50); if (PINB.0 == 1) ( hilfsvariable = 0; ) } } else { PORTD.0 = 1; //LED1 aus PORTD.1 = 1; //LED2 aus PORTD.2 = 1; //LED3 aus } if (test == 2); { PORTD.0 = 1; //LED1 PORTD.1 = 1; //LED2 aus PORTD.2 = 1; //LED3 aus break; } } } wird funktionieren, aber wie gesagt, pfuschig programmiert (war zu faul dir das sauber zu machen... versuchs, und als nächerster schritt würde ich empfehlen dies mit einer schrittkette zu lösen (switch, case)
Hallo Karl heinz, vielleichts kannst du mir auch helfen! bin Afänger und soll zu sagen habe einiege Kapitel von Tutorial "bestanden". mein Problem: mein Testboard hat 2 Taster die ich beliebig benutzen kann, wenn ich die Taster benutzen will Aktiviere ich die "Pull ups" und und funktioniert ganz gut. Nun habe ich ein "Externe Taster Modul" (??) wie im Anhang gelötet also mit 10K als vorwiderstand oder als Pull up es bedeutet jetzt brauche ich die interne Pull up von controller NICHT mehr oder???? Frage 1: Wenn ich im Code "kein Pull up" aktiviere funktioniert mein Modul nicht, aktiviere ich die Pull up dann funktioniert! warum? Frage 2: brauche ich überhaupt die "externe" widerstand, ist sowas Sinnvoll? vielen Dank für die Hilfe Gruß Martin
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.