Forum: Mikrocontroller und Digitale Elektronik STK500 - Codeschloss programmieren


von Simon (Gast)


Lesenswert?

Hallo Zusammen,
wollte mal ein Codeschloss programmieren für den stk500 nur funktioniert 
das nicht ganz.

1
#include <avr/io.h>
2
#include <inttypes.h>
3
4
volatile uint8_t count ;  
5
volatile unsigned int i;
6
uint8_t wert = 0;  // Variable für Rückgabewert
7
8
// ----------------------------getcode Funktion-------------------
9
uint8_t getcode(void) {
10
11
12
13
14
      while(PIND!=0b11111110)             //während taste gedrückt
15
      {
16
              // mach nix^^
17
      }
18
      while(PIND==0b11111110)            //während keine Taste
19
      {
20
      }
21
22
    wert = ~PIND;        // invertiert wiedergeben, da bei Drücken 
23
              // z.B. 0b00000001 die 1 high ist bei den Leds
24
              // und somit nicht leuchtet.
25
          
26
return wert; 
27
28
}
29
//---------------------------------------------------------------
30
31
// ----------------------- Warteschleife-----------------------------------
32
void delay(){
33
34
  for(i=0;i<8000;i++)
35
  {
36
     
37
  }
38
}
39
// ---------------------------------------------------
40
41
int main (void)
42
{
43
  DDRB = 0xff;    
44
  DDRD = 0x00;    
45
  PORTB = 0xff;  // Alle LEDs ausschalten
46
  PORTD = 0xff;  // Pullups einschalten
47
  count = 0;     // Anfangswert für Zählvariable ist Null
48
49
  uint8_t kombi1 = 0b11111000;
50
  uint8_t kombi2 = 0b11110001;
51
  uint8_t kombi3 = 0b11100011;
52
  uint8_t taste1 = 0;
53
  uint8_t taste2 = 0;
54
  uint8_t taste3 = 0;
55
 unsigned int tastenzahl = 1;
56
  uint8_t taste = 0;
57
58
while (1)
59
{
60
 
61
  while (tastenzahl!=0){
62
  
63
  taste = getcode();
64
65
  if (tastenzahl==1) {
66
  taste1=taste;
67
  PORTB=0b00001111;
68
  }
69
70
71
  tastenzahl--;
72
  }
73
74
75
76
if(taste1==kombi1 && taste2==kombi2 && taste3==kombi3)
77
      PORTB = ~taste1;  //Schalte LED0 um
78
79
}
80
81
82
return 0;
83
}



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?

von STK500-Besitzer (Gast)


Lesenswert?

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.

von simon (Gast)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

>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.

von Peter D. (peda)


Lesenswert?


von simon (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Samson (Gast)


Lesenswert?

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.

von Joe (Gast)


Lesenswert?

vielleicht solltest du z.b. so viele zeichen einlesen wie erwartet 
werden und dann erst prüfen ...

von Lehrmann M. (ubimbo)


Lesenswert?

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! =)

von Michael M. (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von simon (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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

von Simon (Gast)


Lesenswert?

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?

von Simon (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Simon (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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)

von Karl H. (kbuchegg)


Lesenswert?

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!

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
Noch kein Account? Hier anmelden.