Guten Abend,
ich hab es geschafft, dass meine LEDs die vier Zustände annimmt.
1) Taste einmal drücken, dann geht die ROTE LED AN
2) Taste zum zweiten mal gedrückt, dann geht die GELBE LED AN und die
ROTE AUS
3) Taste zum dritten mal gedrückt, dann gehen die beiden AN
4) Taste zum vierten mal gedrückt, dann gehen die beiden LEDs AUS.
hier ist einmal mein Code:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<inttypes.h>
4
#include<avr/power.h>
5
6
#define F_CPU 2000000UL
7
#define TASTE_AUF 0
8
#define TASTE_ZU 1
9
10
intmain(void)
11
{
12
uint8_talter_tastenzustand=TASTE_AUF;
13
14
15
DDRB&=~(1<<PB0);
16
DDRB|=(1<<PB1);
17
DDRA|=(1<<PA0)|(1<<PA1);
18
PORTB|=(1<<PB0);
19
20
21
22
23
24
while(1)
25
{
26
27
PORTB&=~(1<<PB1);
28
29
30
if(!(PINB&(1<<PB0)))
31
32
33
alter_tastenzustand++;
34
35
switch(alter_tastenzustand)
36
{
37
case0:PORTA&=~(1<<PA0);
38
PORTA&=~(1<<PA1);break;
39
40
case1:PORTA&=~(1<<PA1);
41
PORTA|=(1<<PA0);break;
42
43
case2:PORTA&=~(1<<PA0);
44
PORTA|=(1<<PA1);break;
45
46
case3:PORTA|=(1<<PA1);
47
PORTA|=(1<<PA0);break;
48
49
default:PORTA&=~(1<<PA0);
50
PORTA&=~(1<<PA1);
51
alter_tastenzustand=TASTE_AUF;
52
}
53
_delay_ms(100);
54
55
56
57
}
58
}
jetzt meine Frage, wenn ich den Taste gedrückt halte, dann laufen die
vier Zustände durch und das möchte ich nicht. Ich möchte, wenn ich den
Taster einmal gedrückt halte, dass nur die ROTE LED AN ist bzw. den
Zustand hat. Also ich will diesen zustand speichern,wie mach ich das?
Liebe Grüße
Sven98
kopfkratz
Es wurde doch schon geschrieben wie man das in einer Statemachine
abbildet.
Statt einfach hochzuzählen mußt Du in jedem Deiner cases die Zustände
ändern.
Ist Dir eigentlich klar was Dein "Zähler" in der Endlosschleife macht ?
Sven Baum schrieb:> jetzt meine Frage, wenn ich den Taste gedrückt halte,
Sven, das hatten wir doch alles schon mal.
Solange du dich von dieser Strategie hier
1
while(1)
2
{
3
...
4
5
if(!(PINB&(1<<PB0)))
6
....
7
8
_delay_ms(100);
9
}
nicht löst, solange wird das nichts. Und wenn du noch 100 mal fragst.
Die korrekte Strategie ist eine Flankenerkennung, die eine Veränderung
des Tastenzustands feststellt
1
uint8_tPinPrevious;
2
uint8_tPinNow;
3
4
5
....
6
PinPrevious=(PINB&(1<<PB0));
7
8
while(1)
9
{
10
11
PinNow=(PINB&(1<<PB0));
12
13
if(PinNow!=PinPrevious)// hat sich der Pin verändert?
14
{
15
if(!PinNow)// Ja, hat er. Was ist er jetzt?
16
{// Gedrückt oder Losgelassen?
17
....// Er ist gedrückt: mach was, der
18
// Benutzer hat gerade den Taster gedrückt
19
....
20
}
21
22
PinPrevious=PinNow;
23
_delay_ms(10);// Pseudoentprellung, in dem die Prellzeit
24
// ausgesessen wird
25
}
26
}
Und wenn du noch 200 mal fragst, die Sache wird deswegen nicht
einfacher. Das ist sowieso schon die abgespeckte Minimalversion mit
integriertem Bauchweh.
Davon losgelöst ist dann die Sache mit dem Zähler, der angibt welche
LED-Kombination leuchten soll. Der Teil kommt dann zum Bleistift dort
rein (aber korrekt schreiben!), wo jetzt die .... Punkte sind. Im
einfachsten Teil machst du bei einem Tastendruck nur das Erhöhen des
Statuszählers. Das Auswerten dieses Zählers und entsprechende
Beschalten der LED kann auch nach der Tastenauswertung erfolgen.
Hallo Karl-Heinz,
ich hab deine Rat befolgt. Am anfang, wollte ich nur die eine LED AN und
AUS bekommen mit einem Tasten druck. Da habe ich diesen Code verwendet.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<inttypes.h>
4
#include<avr/power.h>
5
6
7
#define F_CPU 2000000UL
8
#define TASTE_AUF 0
9
#define TASTE_ZU 1
10
#define TASTE_NEU 1
11
12
intmain(void)
13
{
14
uint8_tneuer_tastenzustand=TASTE_NEU;
15
uint8_talter_tastenzustand=TASTE_AUF;
16
17
18
DDRB&=~(1<<PB0);
19
PORTB|=(1<<PB0);
20
DDRB|=(1<<PB1);
21
DDRA|=(1<<PA0)|(1<<PA1);
22
23
while(1)
24
{
25
26
27
28
if(PINB&(1<<PB0))
29
30
if(alter_tastenzustand==TASTE_ZU)
31
32
{
33
34
PORTA^=(1<<PA0);
35
alter_tastenzustand=TASTE_AUF;
36
}
37
38
if(!(PINB&(1<<PB0)))
39
alter_tastenzustand=TASTE_ZU;
40
}
41
}
Das gleiche Prinzip hab ich jetzt auch getan, aber es funktioniert
nicht.
[ ] Ich bin in der Lage, Code den mir jemand vorgibt, sinngemäss und
vollständig zu übernehmen
[ ] Ich bin nicht dazu in der Lage
Wenn du das Kreuzerl zu oft in der 2-ten Zeile machst, dann solltest du
dir ernsthaft überlegen, dir ein anderes Hobby zu suchen.
> Das gleiche Prinzip
Pustekuchen. Das ist noch nicht mal annähernd an dem, was ich dir
vorgezeigt habe.
Karl Heinz schrieb:>> Das gleiche Prinzip>> Pustekuchen. Das ist noch nicht mal annähernd an dem, was ich dir> vorgezeigt habe.
Ich werde das Gefühl nicht los, du würdest denken, das in meiner Vorlage
eine einzige Zeile die gewünschte Funktionalität ergibt.
Dem ist nicht so!
In der Vorlage ist JEDE Zeile relevant! Erst durch das Zusammenspiel
ALLER Zeilen ergibt sich die geforderte Funktion. Es gibt nicht "die
eine Zeile", die alles verändert.
@Karl Heinz:
Es ist bewundernswert wie Du geduldigt die immer gleichen Fehler
ansprichst und zu korregieren versuchst.
Doch ich denke mal das hier ein massives Verständnisproblem vorliegt.
Wenn der TO einen Zustandsautomaten bauen will sollte er sich erstmal
mit dem Thema auseinander setzen statt sinnlos herumzuprobieren.
Wurde ja schon alles durchgekaut:
1. Zustände definieren und auf Papier z.B. als Kreis zeichnen
2. Übergänge der Zustände via Pfeil einzeichnen
3. Übergangsbedingung an Pfeil schreiben
Das dann in ein simples Ablaufdiagramm gießen und damit implementieren.
So schwierig ist das nicht und dann spielt die Programmiersprache auch
keine Rolle mehr.
Das Problem liegt nicht im Code sondern dem Verständnis was herauskommen
soll ...
kopfkratzer schrieb:> Wenn der TO einen Zustandsautomaten bauen will sollte er sich erstmal> mit dem Thema auseinander setzen statt sinnlos herumzuprobieren.
Less es ihn erst mal ins Hirn bringen, dass nicht jede Funktion damit
erreicht wird, dass man 1 Zeile Code hinschreibt.
Ich denke im Moment entdeckt er gerade, dass es sowas wie Algorithmen
gibt. Also Vorschriften (an Sven gerichtet), die über viele Stufen
laufen und an deren Ende dann eine bestimmte Funktionalität steht. Die
Vorschrift als ganzes ergibt die Funktion. Lass einen teil weg und es
funktioniert nicht mehr.
Wie beim Kuchenbacken. Das ganze Rezept ist die Vorschrift, wie man zu
einer Scahertorte kommt. Lass einen Teil weg und du kriegst keine
Sachertorte mehr.
Karl Heinz schrieb:> Lass einen Teil weg und du kriegst keine> Sachertorte mehr.
Nur das man das Endergebnis trotzdem essen kann :-P
Sven sollte einfach mal das Tutorial durcharbeiten und dazu noch ein
gutes Buch über Algorithmen und allgemein Datenverarbeitung lesen.
Wenn er dann verstanden hat was die eigentliche Herausforderung ist (das
ist NICHT das Programmieren) ist er wesentlich weiter ;-)
Aber soll ja "schnell" fertig werden und so :-P
Hallo Karl Heinz,
herzlichen Dank für deine Hilfe. Ich konnte die letzten Tage nicht
antworten, weil ich krank war.
Ich hab es jetzt hinbekommen hab mir mal dein Beispiel durchgearbeitet
und ich glaube, dass ich es jetzt verstanden habe.
Eine Frage hätte ich da noch.
In meinem Programm siehst Du meine case-Anweisung, weil ich die vier
Zustände haben möchte und das funktioniert auch wunderbar.
Hier nochmal der geämnderte Code:
1
/*
2
* Test.c
3
*
4
* Created: 28.11.2013 17:58:16
5
* Author:
6
*/
7
8
#define F_CPU 2000000UL
9
#include<util/delay.h>
10
#include<avr/io.h>
11
#include<inttypes.h>
12
#include<avr/power.h>
13
14
#include<avr/io.h>
15
#include<util/delay.h>
16
#include<inttypes.h>
17
#include<avr/power.h>
18
19
20
intmain()
21
{
22
uint8_tPinPrevious;
23
uint8_tPinNow;
24
25
uint8_tStatus=0;
26
27
DDRB&=~(1<<PB0);
28
PORTB|=(1<<PB0);
29
DDRB|=(1<<PB1);
30
DDRA|=(1<<PA0)|(1<<PA1);
31
32
PinPrevious=(PINB&(1<<PB0));// Zuweisung : Variable "PinPrevious" = PINB an Port B0 ist 1 (Taster ist nicht gedrückt)
33
34
while(1)
35
{
36
37
PinNow=(PINB&(1<<PB0));// Zuweisung : Variable "PinNow" = PINB an Port B0 ist 1 (Taster ist nicht gedrückt)
38
39
if(PinNow!=PinPrevious)// Abfrage: Hat sich der Pin an Port B0 verändert?
40
{
41
if(!PinNow)// Ja, hat er. Was ist er jetzt?; Gedrückt oder Losgelassen?; Er ist gedrückt: mach was, der Benutzer hat gerade den Taster gedrückt
42
{
43
44
if(Status==4)
45
Status=0;
46
47
Status++;
48
switch(Status)
49
{
50
51
case0:PORTA&=~(1<<PA0);
52
PORTA&=~(1<<PA1);break;
53
54
case1:PORTA&=~(1<<PA1);
55
PORTA|=(1<<PA0);break;
56
57
case2:PORTA&=~(1<<PA0);
58
PORTA|=(1<<PA1);break;
59
60
case3:PORTA|=(1<<PA1);
61
PORTA|=(1<<PA0);break;
62
63
default:PORTA&=~(1<<PA0);
64
PORTA&=~(1<<PA1);
65
}
66
67
}
68
69
PinPrevious=PinNow;
70
_delay_ms(10);// Pseudoentprellung, in dem die Prellzeit ; ausgesessen wird
71
}
72
73
74
75
//if( Status == 0 )
76
//PORTA |= ( 1 << PA0 );
77
//else
78
//PORTA &= ~( 1 << PA0 );
79
80
//if( Status == 1 )
81
//PORTA |= ( 1 << PA1 );
82
//else
83
//PORTA &= ~( 1 << PA1 );
84
85
//if( Status == 2 )
86
//PORTA &= ~( 1 << PA0 );
87
88
//if( Status == 3 )
89
//PORTA &= ~( 1 << PA1);
90
}
91
}
Ich hatte es do versucht wie Du es mir gezeigt hast (Aus kommentiert),
diese haben auch funktioniert aber nur für die ersten zwei Zustände.
Also Blaue LED AN und Grüne AUS!
Und Grüne LED AN und Blaue AUS!
Ich bin nicht dahinter gekommen die anderen zwei Zustände zu
programmieren, deswegen habe ich meine case-Anweisung verwendet.
Hättest Du da vielleicht noch eine Idee?
lg
Sven
die Reihenfolge falsch.
Nimm mal an, Status hätte den Wert 0.
So weit so gut.
Jetzt drückst du eine Taste. Was passiert?
1
if(Status==4)
Hat Status den Wert 4? Nein. Also wird der abhängige Teil nicht
ausgeführt.
Wie gehts weiter?
1
Status++;
aus 0 wird 1. So weit so gut.
wieder drückst du die Taste. Was passiert jetzt?
1
if(Status==4)
Hat Status den Wert 4? Nein. Status ist jetzt ja 1, und 1 ist nicht 4.
Also wird die abhängige ANweisung nicht ausgeführt und es geht weiter
mit
1
Status++;
Aus 1 wird 2
Nächster Tastendruck. Wieder landet der Code hier
1
if(Status==4)
2 ist nicht 4, also wird das davon abhängige 0-setzen von Status nicht
gemacht
1
Status++;
aus 2 wird 3.
Nächster Tastendruck
1
if(Status==4)
Status hat den Wert 3, daher passiert wieder weiter nichts und es geht
weiter mit
1
Status++;
aus 3 wird 4.
Moment, deine if weiter unten behandeln aber den Fall gar nicht, dass
Status jemals 4 werden könnte!
Nächster Tastendruck. Der Code landet wieder hier
1
if(Status==4)
Diesmal hat STatus den Wert 4. Also wird ausgeführt
1
Status=0;
aus 4 wird 0. Wie gehts weiter? Mit
1
Status++;
Aus der soeben zugewiesenen 0 wird eine 1.
usw. use.
Deine Statusvariable nimmt also bei den Tastendrücken nacheinander diese
Werte an
1
0 1 2 3 4 1 2 3 4 1 2 3 4 ....
die erste 0 ist nur mehr oder weniger zufällig entstanden, weil Status
vor dem ersten Tastendruck mit 0 initialisiert wurde.
Das passt also schon mal nicht.
Dann
1
//if( Status == 0 )
2
//PORTA |= ( 1 << PA0 );
3
//else
4
//PORTA &= ~( 1 << PA0 );
5
6
//if( Status == 1 )
7
//PORTA |= ( 1 << PA1 );
8
//else
9
//PORTA &= ~( 1 << PA1 );
10
11
//if( Status == 2 )
12
//PORTA &= ~( 1 << PA0 );
13
14
//if( Status == 3 )
15
//PORTA &= ~( 1 << PA1);
bei den Stati 2 und 3 schaltest du ja jeweils nur einen Port-pin aus.
Aber wie soll da was eingeschaltet werden?
Mach dir halt mal eine Tabelle! Bei welchem Status (diesmal dann aber
mit den krorrekten Status-Nummern), muss welcher Output-Pin wie stehen?
Und das implementierst du dann.
Im ersten Abschnitt der Antwort rede von der Stelle hier
1
....
2
while(1)
3
{
4
5
PinNow=(PINB&(1<<PB0));// Zuweisung : Variable "PinNow" = PINB an Port B0 ist 1 (Taster ist nicht gedrückt)
6
7
if(PinNow!=PinPrevious)// Abfrage: Hat sich der Pin an Port B0 verändert?
8
{
9
if(!PinNow)// Ja, hat er. Was ist er jetzt?; Gedrückt oder Losgelassen?; Er ist gedrückt: mach was, der Benutzer hat gerade den Taster gedrückt
10
{
11
12
# if( Status == 4 )
13
# Status = 0;
14
#
15
# Status++;
16
17
...
wir sind wieder mal soweit, dass du Programm übernimmst (gut, ich hab es
dir gegeben), ohne darüber nachzudenken und was noch viel schlimmer ist,
sie zu verändern ohne darüber nachzudenken, was du eigentlich tust und
welche Auswirkungen das hat.
Das stimmt zwar aber ich hab dein Programm nicht einfach soooo
übernommen, ich hab versucht es zu verstehen und das hab ich jetzt auch.
Das Programm hattest Du mir schon vor paar Wochen gegeben und ich hab es
auch nicht sofort übernommen, weil ich es nicht verstanden habe. Ich
könnte auch das Programm neu schreiben und mit neuen Variablen aber das
wäre das gleiche.
Hallo Karl Heinz,
ich hätte dann mal eine Frage zur deiner Erklärung vom 02.12.20013 17:16
Uhr!
Wenn ich das soweit verstanden habe, dann dürft die LED bei diesem
Befehl ja nicht leuchten oder?
.
.
.
Status++;
if( Status == 2 )
Status = 0;
}
PinPrevious = PinNow;
_delay_ms( 10 ); // Pseudoentprellung, in dem die Prellzeit
// ausgesessen wird
}
if( Status == 0 )
PORTA |= ( 1 << PA0 ); // Blaue LED AN
else
PORTA &= ~( 1 << PA0 ); // Blaue LED AUS
}
}
weil laut deiner Erklärung ( so weit ich das verstanden habe ) ist ja
der if( Status == 2 ) und wenn ich jetzt den Taster drücke, dann bekomme
ich ein 1. Und da in "if( Status == 2) steht, passiert nichts.