ICh habe zu BEginn erstmal mit einer TAste gearbeitet nur folgendes:
Wenn ich eine Taste drücke, dann möchte ich diese in der main Funktion
auch ausgeben, sozusagen zum Test, ob diese richtig eingelesen wurde.
Stattdessen werden alle Tasten ausgegeben, stimmt was nicht mit der
getcode() FUnktion oder warum werden in der Variable "wert" alle Lampen
ausgegeben bzw. gespeichert?
Beim STK500 sind Tasten und LEDs low-aktive.
Das bedeutet, das eine gedrückte Taste "0" liefert und eine LED durch
Schreiben einer "0" ins Register leuchtet.
Durch die Logik deines Programms muss man nicht durchsteigen, oder?
Sinnvolle Kommentare im Programm würden hier schon helfen.
wie gesagt hatte ich ein Programm geplant, indem ich z.b. einen
vorgegebenen code vorgebe und wenn ich diesen code richtig eingebe, z.b.
alle Lampen angehen. Nur klappt das nicht wirklich gut.
>wie gesagt hatte ich ein Programm geplant, indem ich z.b. einen>vorgegebenen code vorgebe und wenn ich diesen code richtig eingebe, z.b.>alle Lampen angehen. Nur klappt das nicht wirklich gut.
Nimm den Plan und verbrenne ihn.
Der funktioniert nicht.
Hilft mir nicht wirklich weiter. Also als Anfang reicht es, wenn das stk
auf eine eingabe wartet. Also z.b. 3 tasten oder eine festgelegte zahl.
Dann soll eine if anweisung oder so vergleichen, ob der eingegebene wert
mit dem vorher im programm festgelegten übereinstimmt und diesem dann
ausgeben oder so. Aber irgendwie gelingt mir das nicht
simon schrieb:> Hilft mir nicht wirklich weiter. Also als Anfang reicht es, wenn das stk> auf eine eingabe wartet.
Gut.
Dann fang damit an, das zu programmieren
> Also z.b. 3 tasten oder eine festgelegte zahl.
schon zu kompliziert.
1 Taste. Nicht mehr.
> Dann soll eine if anweisung oder so vergleichen,
Du machst einen Fehler.
Du denkst du kannst dein Programm 'so irgendwie' aus dem Ärmel schütteln
ohne dir vorher überlegt zu haben, wie das alles laufen soll.
> ob der eingegebene wert> mit dem vorher im programm
Es geht nicht darum, dass ein Wert mit einem anderen Wert übereinstimmt.
Du hast eine Abfolge von Tasten.
Und diese Abfolge von Tasten muss mit einer vorher festgelegten
übereinstimmen.
Wenn du das Codeschloss bist, und ich hintereinander die Tasten drücke
'5', '8', '2'
wie entscheidest du, ob diese Sequenz die richtige ist.
Was ist, wenn ich drücke
'6', '7', '5', '8', '2'
(angenommen 5 8 2 wäre korrekt)
ist das dann immer noch korrekt, obowhl ich vorher andere Tasten
gedrückt habe?
Wie behandelst du das?
Geh dein Vorgehen in Gedanken durch und formuliere es so, dass meine 2
jähriger Enkel die Arbeit des Codeschlosses machen kann, wenn er sich
nur stur an deine Vorgabe hält. Du kannst dein Verfahren in Form von
Diagrammen zu Papier bringen. Du kannst auf dem Zettel radieren und
sonst was weiß ich alles machen. Aber du darfst nichts benutzen, was
großartig Intelligenz erfordert.
Erst wenn du das hast (und auf dem Papier ein paar mal durchgespielt
hast, ob das wirkich funktioniert), bist du soweit, dich an den Computer
zu setzen und zu programmieren.
Hi,
also Gedanken habe ich mir schon gemacht. Aber es klappt mit der
Umsetzung einfach nicht:
solange keine Tasten gedrückt:
[tu nichts]
wenn Tasten gedrückt:
[warten] (Tastenentprellung)
[prüfen ob richtige Tastenkombination]
wenn ja:
[Tastenkombination ausgeben]
wenn nein:
[Abbruch und Neuanfang]
ICh habe schon überlegt, ob es mit Arrays einfacher währe, als mit
integer Variablen. Nur wie gesagt entstand hieraus der obige Code, der
nicht ganz funktioniert. Eventuell habe ich überlegt, alle drei Eingaben
also von einem dreistelligen Code in einzelne Variablen taste1, taste2
und taste 3 abzuspeichern und dann mit UND BEdingungen mit den
festgelegten Tastenkombinationen kombi1 zu vergleichen. nur wie gesagt
klappt es mit der Umsetzung einfach nicht.
Simon schrieb:> // ----------------------- Warteschleife-----------------------------------> void delay(){>> for(i=0;i<8000;i++)> {>> }> }> // ---------------------------------------------------
Meister du weisst schon, dass ein so gut wie jeder Compiler optimiert?
Sowas löscht der dir sofort. Wenn du in der ASM nachschaust dann wirst
du diese Passage nirgendwo finden.
Simon schrieb:> uint8_t wert = 0; // Variable für Rückgabewert
Wozu wird der Rückgabewert global initialisiert ? Damit ist der Sinn
einer jeden Funktion hinfällig.
aus funktion() wird der Rückgabewert! Ist dir klar was eine Funktion
macht?
simples sinnloses BSP:
ANSI C:
int main(){
if(haha()==88) [tue dies und jenes];
}
int haha(){
return(88);
}
[tue dies und jenes] wird ausgeführt. Dazu bedarf es keiner globalen
Variable.
Darf ich neugirig fragen wieviel du schon auf µC gemacht hast?
Sorry aber fang erstmal mit einem Blinklicht an ^^
Für deine Basic's: Stichwort Entprellung !
Wenn man bei dir eine Taste drück würde die gleich ein paar Tausend mal
eingelesen werden bevor man in der Lage wäre die Taste wieder
loszulassen! =)
Lehrmann Michael schrieb:> Sowas löscht der dir sofort. Wenn du in der ASM nachschaust dann wirst> du diese Passage nirgendwo finden.
nö.
> Für deine Basic's: Stichwort Entprellung !
waaah.
fals'ch r geht´ s fast nimmer .
> Wenn man bei dir eine Taste drück würde die gleich ein paar Tausend mal> eingelesen werden bevor man in der Lage wäre die Taste wieder> loszulassen! =)
DA liegt sein problem. und sonst nirgends - von schlechtem
programmierstil abgesehen.
simon schrieb:> Hilft mir nicht wirklich weiter. Also als Anfang reicht es, wenn das stk> auf eine eingabe wartet.
Warten ist schonmal ganz schlecht, da die CPU nichts anderes machen
kann.
Du mußt Dein Denken umstellen auf Ereignisse.
D.h. die Mainloop nudelt immer durch und prüft einzelne Ereignisse.
Ist ein Ereignis eingetreten (z.B. Taste wechselt von Losgelassen nach
Gedrückt), dann führt sie die entsprechende Behandlung aus, ansonsten
macht sie einfach nix.
> Also z.b. 3 tasten oder eine festgelegte zahl.> Dann soll eine if anweisung oder so vergleichen, ob der eingegebene wert> mit dem vorher im programm festgelegten übereinstimmt und diesem dann> ausgeben oder so.
Mit "oder so" kann die CPU nix anfangen. Du mußt ihr ganz genau sagen,
was zu tun ist. Und dazu programmiert man nicht wild drauf los, sondern
macht sich erstmal einen Programmablaufplan (in Worten, nicht als
Programm).
> Aber irgendwie gelingt mir das nicht
Du darfst eine Aufgabe nicht als großen Brocken ansehen, sondern mußt
sie in einzelne Teilaufgaben aufteilen.
Wenn Du eine Teilaufgabe nicht programmieren kannst, ist sie immer noch
zu groß und Du mußt sie weiter aufteilen.
Z.B. wird alle Nase lang eine Taste entprellen und die Drücken-Flanke
erkennen benötigt. Deshalb ist es sinnvoll, dafür ne extra Funktion
(DEBOUNCE) zu schreiben.
Ganz blöd ist es, diese beiden Funktionen in andere Aufgaben mit
hineinzumanschen. Denn dann muß man sie immer wieder neu schreiben und
ihr (Nicht-)Funktionieren hängt von der Laufzeit ab.
Es gilt: Teile und Herrsche.
Peter
Samson schrieb:
Zum Rest wurde ja schon viel gesagt
> solange keine Tasten gedrückt:> [tu nichts]> wenn Tasten gedrückt:> [warten] (Tastenentprellung)> [prüfen ob richtige Tastenkombination]
Dieser Schritt: prüfen ob richtige Kombination
Wie genau machst du das?
Beschreibe diesen Schritt mal im Detail!
> wenn ja:> [Tastenkombination ausgeben]> wenn nein:> [Abbruch und Neuanfang]>> ICh habe schon überlegt, ob es mit Arrays einfacher währe, als mit> integer Variablen.
Ich würde es so machen:
In einem Array habe ich die richtige Kombination.
Weiterhin habe ich einen Zähler, der mir sagt, wieviele Ziffern der
richtigen Kombination bis jetzt richtig eingegeben wurden.
Also zb. die richtige Kombination lautet 8 3 5 7
uint8_t Kombi[] = { 8, 3, 5, 7 };
Dazu der Zähler, der natürlich bei 0 anfängt
uint8_t Correct = 0;
Die Taste 8 wird gedrückt.
So jetzt vergleiche ich. Ist Kombi[Correct] gleich der Eingabe?
also: ist 8 gleich 8?
Ja, das ist der Fall. Also habe ich eine korrekte Stelle mehr.
Der Benutzer drückt 3
Wieder ist Kombi[Correct] gleich der Eingabe ( 3 == 3 )
Ist der Fall. Also wird Correct wieder erhöht.
Jetzt drückt der Benutzer 2
Kombi[Correct] == Eingabe?
Nein, das ist nicht der Fall. 5 ist nicht gleich 2.
Und damit ist die bisherige Eingabe hinfällig, Correct wird wieder auf 0
gesetzt.
Das hier hat den Vorteil, dass du jeden Tastendruck einzeln für sich
behandeln kannst. Der Benutzer kann zu jedem beliebigen Zeitpunkt
anfangen die Kombination einzugeben. Hat er was falsches eingegeben,
braucht er gar nichts tun, er tippt einfach weitr auf den Tasten. Sobald
er die geforderten Tasten in der richtigen Reihenfolge eingegeben hat,
kannst du am Wert von Correct erkennen, dass die richtige Kombination
gegeben wurde.
> Nur wie gesagt entstand hieraus der obige Code, der> nicht ganz funktioniert.
Nicht ganz ist gut.
Du bist gaaaanz weit weg, diesen Code jemals zum funktionieren zu
bringen.
ok, werde mich heute abend daran machen. Nur noch eine frage. Habe
vorher auch schon ein programm geschrieben, wo man erst wartet, bis
taste losgelassen wurde. Habe das mit while schleife gemacht. Aber
anscheinend muss ich zum entprellen es für diese aufgabe anders machen
und das verstehe ich nicht. Bei einer einfacheren aufgabe habe ich
mittels zwei while schleifen bedingungen gemacht also Pind ist gleich
0xff etc. Das ist doch das entprellen oder?
simon schrieb:> ok, werde mich heute abend daran machen. Nur noch eine frage. Habe> vorher auch schon ein programm geschrieben, wo man erst wartet, bis> taste losgelassen wurde. Habe das mit while schleife gemacht. Aber> anscheinend muss ich zum entprellen es für diese aufgabe anders machen> und das verstehe ich nicht. Bei einer einfacheren aufgabe habe ich> mittels zwei while schleifen bedingungen gemacht also Pind ist gleich> 0xff etc. Das ist doch das entprellen oder?
Nein, das hat mit entprellen nichts zu tun.
http://www.mikrocontroller.net/articles/Entprellung
Also ich hab wie gesagt mal was anders programmiert und für das drücken
und loslassen der Taste einfach zwei While Schleifen genommen, wenn das
kein Entprellen ist, was dann?
Also hab nochmal geschaut und tatsächlich haben wir für unsere PRogramme
in der Uni keine fertigen Funktionen verwendet und für Tastenentprellung
Schleifen genommen wie z.B. diese:
void delay() //wartefunktion
{
for(int i=0;i<10000;i++)
{
for(int j=0;j<1000;j++)
{;}
}
}
Das ist natürlich nicht das optimalste, aber nur so, sagte der Prof,
können wir den Ablauf besser verstehen. Also wieviel Takte etc. nötig
sind, um etwas so einfaches zum laufen zu bekommen.
Entprellen und Flanke erkennen ist eine sehr wichtige Aufgabe.
Daher ist es sinnvoll, das einmal richtig zu lösen, damit man es ein für
alle mal vom Tisch hat und zum eigentlichen Programmieren kommt.
Mach also erstmal ne Toggle-Taste, d.h. einmal drücken -> LED ein,
nochmal drücken -> wieder aus usw.. Dabei darf die Drückdauer keine
Rolle spielen.
Und dann der Clou, mach es für 2 Tasten und 2 LEDs unabhängig
voneinander. D.h. jede Taste toggled nur ihre LED, egal wie die andere
Taste gerade ist (Gedrückt, Losgelassen).
Wenn das für eine LED sauber gamcht wurde, geht das ganz leicht. Einfach
die Routine ein zweites Mal aufrufen mit der zweiten Taste als Argument.
Wenn sich die Routinen aber gegenseitig verklemmen, hast Du einen Fehler
gemacht und mußt nochmal zurück zu einer LED.
Eine verklemmende oder nicht sauber entprellende Routine wird Dir immer
wieder auf die Füße fallen, wie ein 10Pfund Hammer (tut weh).
Peter
hmm, ja mir gings nur darum, das meine Schleife ja auch nicht ganz
falsch ist, ist zwar kein richtiges und sauberes Entprellen, aber
erfüllt für den Anfang seinen Zweck. Aber werde mich mit dem Enprellen
auch beschäftigen.
Simon schrieb:> Das ist natürlich nicht das optimalste, aber nur so, sagte der Prof,> können wir den Ablauf besser verstehen. Also wieviel Takte etc. nötig> sind, um etwas so einfaches zum laufen zu bekommen.
Sage deinem Professor einen schönen Gruß von mir.
Ich geb ihm gerne Nachhilfe.
(Wie leider bei so vielen Akademikern die ihr Leben lang die Uni nie
verlassen haben: Er hat von praktischer Arbeit keine Ahnung von Tuten
und Blasen)
Simon schrieb:> hmm, ja mir gings nur darum, das meine Schleife ja auch nicht ganz> falsch ist, ist zwar kein richtiges und sauberes Entprellen, aber> erfüllt für den Anfang seinen Zweck. Aber werde mich mit dem Enprellen> auch beschäftigen.
Der springende Punkt ist: Das entprellt nichts.
Das hier
1
while(PIND!=0b11111110)//während taste gedrückt
2
{
3
// mach nix^^
4
}
5
while(PIND==0b11111110)//während keine Taste
6
{
7
}
kriegt jeden einzelnen Preller mit. Dein µC ist viiiiieeeel schneller
als der Taster überhaupt prellen kann. Das einzige was es tut: Es wartet
immer darauf, dass der Taster wieder in seine Urlage zurückkommt. Aber
das tut er aus Programmsicht für Millisekunden während des Prellens
auch. Millisekunden sind für einen mit 16Mhz getakteten µC eine halbe
Ewigkeit!