Forum: Mikrocontroller und Digitale Elektronik Taster 1 5x drücken LED1 an, Taster 2 löscht LED 1 wieder


von Michael M. (anfaenger2011)


Lesenswert?

Hallo zusammen,

zuvor muss ich gestehen...ich bin ein Anfänger. Bitte nicht gleich 
ausbuhen ;P

Programmsprache: Assembler
verwendete Hardware: Atmel Evaluationboard + Atmega 32
Meine Aufgabenstellung:

LED 1 (PORTD PD5) soll nach 5x drücken des Tasters 1 (PIND PD2) 
eingeschaltet und mit Taster 2 (PIND PD3) wieder ausgeschaltet werden.

Mir fehlt noch ein bisschen das Verständnis. Wenn ich das Programm 
gedanklich durchgeh, find ich keinen Fehler. Also von meiner Seite, ist 
der Code fehlerfrei, doch auf den µC geladen, funktioniert er nicht.

Hier mein Code:
1
loop:            ldi r17, 1;  // Startwert 1
2
3
warte:   
4
    ldi r16,0x02;
5
    rcall zeitschleife; // Pause
6
    sbis pind,2;  // Ist Taster 1 gedrückt?
7
    rcall S1;    // Wenn nicht --> S1
8
    inc r17;    // Wenn ja --> zähle R17 + 1
9
    cpi r17,6;  // Vergleiche R17 mit 6
10
    brne warte;   // R17 ungleich 6, spring Tasterabfr.
11
    rcall led_1_on;  // R17 ist gleich 6, spring UP led_1_on
12
S1:
13
    sbis pind,3;  // Ist Taster 2 gedrückt?
14
    rcall S2;    // Wenn nicht --> S2
15
    rcall led_off;  // Wenn ja --> springe UP led_off
16
17
S2:
18
    rcall warte;  // spring zurück zu "warte:"
19
20
led_off:        // schaltet LED 1 aus
21
    cbi portd, pb5;  
22
    rcall loop;
23
24
led_1_on:        // schaltet LED 1 an
25
    sbi portd, pb5;
26
    rcall loop;
27
28
zeitschleife:
29
    dec r16;
30
    brne zeitschleife;

Wie gesagt, rein gedanklich müsste es eigentlich funktionieren, doch die 
Praxis sieht leider anders aus.

Danke schon mal für Eure "ich hoffe" positiven Beiträge.

Gruss Micha

: Verschoben durch User
von Stefan B. (stefan) Benutzerseite


Lesenswert?

Dein Programm benutzt Unterroutinen (rcall) ohne Stackinitialisierung. 
Das stürzt ab. AVR-Tutorial: Stack

Mechanische Taster prellen. Du meinst, dass du einmal drückst, der AVR 
registriert aber zig Tastendrücke! Du musst dich um die Entprellung 
kümmern! Die Hardware-Entprellung der Pollinboards ist nicht perfekt 
(und kann selber Probleme machen [[Diskussion:Pollin ATMEL 
Evaluations-Board]])

von Karl H. (kbuchegg)


Lesenswert?

Ein weiterer Fehler ist, dass du deinen µC komplett unterschätzt, was 
Speed angeht.

Das hier
1
    ldi r16,0x02;
2
    rcall zeitschleife; // Pause
3
4
....
5
6
zeitschleife:
7
    dec r16;
8
    brne zeitschleife;

hat dein µC durchgeackert, noch ehe du beim Augenzwinkern einmal das 
Augenlid zur Hälfte zubringst.


Um einen Tastendruck festzustellen musst du

  in einer Schleife warten, bis der Pin von 1 auf 0 geht (du drückst den 
taster nieder)
  dann weiter warten bis der Pin wieder von 0 auf 1 geht (du lässt den 
Taster wieder los)

Beide Aktionen verlaufen aus Sicht des µC in extremer Zeitlupe. So wie 
es für dich eine halbe Ewigkeit dauert, bis der Rasen vor dem Fenster 3 
Zentimeter gewachsen ist.

Im Simulator scheint der Code für dich zu funktionieren, weil du dort 
als Mensch den Takt vorgibst und so die Geschwindigkeit des simulierten 
Prozessors extrem drosselst und an dich anpasst (damit du was siehst). 
Aber dein realer Prozessor arbeitet viele Tausend mal schneller.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@ Michael Müller

Du hast auch eine vierdimensionale Unendlichkeitsschleife gebaut: loop: 
... rcall loop; plus andere. Lies dir die Doku von RCALL vs. RJMP mal 
durch.

von Michael M. (anfaenger2011)


Lesenswert?

Oje....das war mir nicht bewusst. Danke...ich werd gleich mal lesen

von Michael M. (anfaenger2011)


Lesenswert?

Stefan B. schrieb:
> Mechanische Taster prellen. Du meinst, dass du einmal drückst, der AVR
> registriert aber zig Tastendrücke! Du musst dich um die Entprellung
> kümmern! Die Hardware-Entprellung der Pollinboards ist nicht perfekt
> (und kann selber Probleme machen Diskussion:Pollin ATMEL
> Evaluations-Board)

Muss ich die Entprellung auch verstehen? Reicht es hin den Code "blind" 
ins Programm/UP zu kopieren. Wenn ich ehrlich bin, ist das ja sau schwer 
zu verstehen. Gerade ich, als Anfänger.

Gruss Micha

von Michael M. (anfaenger2011)


Lesenswert?

Den Stack hatte ich anfangs versucht zu Initialisieren mit Hilfe:
1
...
2
ldi r18, LOW(RAMEND)    ; Untere 8 bit des 16 bit-Wertes RAMEND laden
3
out SPL, r18
4
ldi r18, HIGH(RAMEND)   ; Obere 8 bit laden
5
out SPH, r18
6
7
loop:   ldi r17, 1;    // Startwert 1
8
...

Doch das Problem war nicht behoben, ich nehm mal an...es liegt an dieser 
"Taster-Entprell-Geschichte". Okay, also die Initialisierung lass ich 
dann mal im Code.

Frage: Wann muss der Stack eigentlich initialisiert werden? So wie ich 
das verstanden hab....*immer*. Seh ich das richtig?

Gruss Micha

von Karl H. (kbuchegg)


Lesenswert?

Michael Müller schrieb:

> Muss ich die Entprellung auch verstehen? Reicht es hin den Code "blind"
> ins Programm/UP zu kopieren.

Das Problem ist, dass dein Pollin Board die Tasten genau anders rum 
auswertet, als es üblich ist.
Daher musst du zumindest ein bischen verstehen was da abgeht.

Das hier
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten
könnte dir helfen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Copy & Paste reicht nicht, vor allem bei den komplizierteren Verfahren.

Das einfache Warteschleifenverfahren solltest du aber schnell verstehen 
und selbst programmieren können:

Wenn Zustand der Taste abgefragt wird, den nicht sofort an das Programm 
melden bzw. darauf reagieren, sondern paar zig Millisekunden warten (die 
typ. Zeit in der ein Taster prellt) und dann noch mal den stabilisierten 
Zustand abfragen.

von Michael M. (anfaenger2011)


Lesenswert?

Stefan B. schrieb:
> Copy & Paste reicht nicht, vor allem bei den komplizierteren Verfahren.

Hast recht. Doch als blutiger Anfänger ist das gar nicht so einfach zu 
verstehen.

Ich kann zwar eine Zeitschleife in C (als for-Schleife), doch in 
Assembler ist das gar nicht so einfach.

Du meinst bestimmt folgendes:
1
     mov p5,#0xff;
2
b11: mov r2,#0xff;
3
t2 : mov r1,#0xff;
4
t1 : djnz r1, t1;
5
     djnz r2, t2;
Doch ich hatte immer vor eine Schleife mit folgendem zu realisieren:
1
zeitschleife:
2
    dec r16;
3
    brne zeitschleife;
Gruss Micha

von Karl H. (kbuchegg)


Lesenswert?

Michael Müller schrieb:

> Du meinst bestimmt folgendes:
>
1
>      mov p5,#0xff;
2
> b11: mov r2,#0xff;
3
> t2 : mov r1,#0xff;
4
> t1 : djnz r1, t1;
5
>      djnz r2, t2;
6
>
> Doch ich hatte immer vor eine Schleife mit folgendem zu realisieren:
>
1
> zeitschleife:
2
>     dec r16;
3
>     brne zeitschleife;
4
>


Mal abgesehen davon, dass die AVR keinen djnz haben.
Wo genau liegt jetzt deiner Meinung nach der Unterschied zwischen einem 
djnz und der Sequenz  dec / brne

Logisch gesehen machen beide genau dasselbe. Nur dass es bei einem djnz 
in einem Befehl ist und beim AVR sind es eben 2 Befehle. Aber die 
Auswirkung, von einer höheren Warte aus gesehen, sind genau gleich. Ein 
Register wird um 1 heruntergezählt und wenn dadurch das Register nicht 0 
geworden ist, wird ein Sprung veranlasst, bzw. wenn 0 erreicht ist, wird 
nicht gesprungen.

von Michael M. (anfaenger2011)


Lesenswert?

Karl heinz Buchegger schrieb:
> Mal abgesehen davon, dass die AVR keinen djnz haben.
> Wo genau liegt jetzt deiner Meinung nach der Unterschied zwischen einem
> djnz und der Sequenz  dec / brne

Aha...langsam klart der Himmel auf. Wir lernen nämlich mit nem Buch über 
den 8051. Und dort haben wir immer mit djnz programmiert.

Gruss Micha

von Skua (Gast)


Lesenswert?

RET
am ende vom Unterprogramm schadet auch nicht.

von Karl H. (kbuchegg)


Lesenswert?

Michael Müller schrieb:
> Karl heinz Buchegger schrieb:
>> Mal abgesehen davon, dass die AVR keinen djnz haben.
>> Wo genau liegt jetzt deiner Meinung nach der Unterschied zwischen einem
>> djnz und der Sequenz  dec / brne
>
> Aha...langsam klart der Himmel auf. Wir lernen nämlich mit nem Buch über
> den 8051. Und dort haben wir immer mit djnz programmiert.

OK
Du kannst natürlich in Massen gewisse 'Ideen' und 'Konzepte' von einer 
Plattform auf eine andere übertragen. Aber tu dir selbst einen Gefallen 
und fang bei deinem AVR wieder von der Pieke auf vorne an. Vieles davon 
wird dir bekannt vorkommen, vieles ist aber auch völlig anders.

AVR-Tutorial

von Michael M. (anfaenger2011)


Lesenswert?

Stefan B. schrieb:
> Lies dir die Doku von RCALL vs. RJMP mal

@Stefan: Kannst Du mir mal bitte den Link dazu posten. Ich finde den 
Beitrag nicht. "Hab aber die Augen offen".

von Michael M. (anfaenger2011)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aber tu dir selbst einen Gefallen
> und fang bei deinem AVR wieder von der Pieke auf vorne an. Vieles davon
> wird dir bekannt vorkommen, vieles ist aber auch völlig anders.

Dazu müsste man wissen, das der AVR überhaupt kein djnz versteht. Das 
wusste ich nicht und wurde auch nie im Unterricht erwähnt. Danke für den 
Hinweis!

von Karl H. (kbuchegg)


Lesenswert?

Michael Müller schrieb:

> Dazu müsste man wissen, das der AVR überhaupt kein djnz versteht. Das
> wusste ich nicht und wurde auch nie im Unterricht erwähnt. Danke für den
> Hinweis!


Ähm.
Bei Assembler bist du auf unterster Ebene. Sozusagen direkt an der 
Maschine. Jeder Prozessortyp ist anders. EIn AVR aus der Mega Serie 
versteht andere Befehle, verhält isch anders als ein 8051. Der wiederrum 
ist völlig anders zu programmieren als ein Pentium. Welcher wieder 
anders funktioniert als eine RS6000 Risc CPU. Die anders aufgebaut ist 
als eine VAX CPU usw. usw.

Mit Assembler bist du direkt mitten im Geschehen, auf der nackten 
Hardware. Du schaltest sozusagen dein Auto-Getriebe nicht dadurch, dass 
du den üblichen Ganghebel mit der üblichen H-Schaltung betätigst, 
sondern indem du selber im Getriebe Zahnräder verschiebst, während du 
den Lüfter im Innenraumgebläse von Hand drehst und 21, 22 vor dich 
hinmurmelst um dann den Scheibenwischer einmal von links nach rechts und 
zurück zu bewegen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Michael Müller schrieb:

> @Stefan: Kannst Du mir mal bitte den Link dazu posten. Ich finde den
> Beitrag nicht. "Hab aber die Augen offen".

Das nennt sich Instruction Set
http://www.google.de/search?hl=de&q=avr+instruction+set&btnG=Google-Suche&meta=

Der Link steht auch ziemlich vorne im AVR-Tutorial, nämlich im 
Kapitel AVR-Tutorial: IO-Grundlagen - das was du machst: 
Input/Eingabe mit Taster und Output/Ausgabe an LED

von Michael M. (anfaenger2011)


Lesenswert?

Alles klar @all! Ich werd jetzt erstmal eine "Lese-Std." einlegen 
müssen, um mich weiter dem Problem zu stellen.

Gruss Micha

von Michael M. (anfaenger2011)


Lesenswert?

Aber mal im ernst, es ist ganz schön deprimierend.

Man probiert was aus, es geht nicht. Man ändert was, es geht nicht. Man 
tippt wieder was ein und es funktioniert immer noch nicht. Irgendwann 
möchte man den ganzen Sch**** in die Ecke pfeffern und sich nen Bierchen 
gönnen.

Das größte Problem: Im I-Net gibt es keine "für Anfänger" geeignete 
Tutorials...die einen langsam und Schritt für Schritt an die Materie 
ranführen. Ich vermisse einen "Assembler für Dummies"-Kurs

Gruss Micha

von Karl H. (kbuchegg)


Lesenswert?

Michael Müller schrieb:

> Man probiert was aus, es geht nicht. Man ändert was, es geht nicht. Man
> tippt wieder was ein und es funktioniert immer noch nicht. Irgendwann
> möchte man den ganzen Sch**** in die Ecke pfeffern und sich nen Bierchen
> gönnen.

Willkommen im Club.
Das ist Millionen von Programmierern vor dir nicht anders ergangen.
Und die hatten noch nicht einmal ein Web, sondern mussten sich die 
Informationen noch aus Büchern zusammensuchen, sofern sie die überhaupt 
hatten. Die meisten hatten nicht viel mehr als das Instruction Set 
Manual, in der alle Befehle aufgelistet sind und welche Auswirkungen sie 
haben. Wie man die dann sinnvoll kombiniert mussten sie selber 
rausfinden.

> Das größte Problem: Im I-Net gibt es keine "für Anfänger" geeignete
> Tutorials...die einen langsam und Schritt für Schritt an die Materie
> ranführen.

Doch gibt es.
Für AVR-CPUs zb das hier ansässige
AVR-Tutorial

> Ich vermisse einen "Assembler für Dummies"-Kurs

Den wird es so auch nicht geben.
Assembler ist immer auf die Hardware bezogen.
Es gibt ja auch keinen 'Fremdsprachen für Anfänger' Kurs, der universell 
gleichermassen für Italienisch, Arabisch und Russisch geeignet ist.

von Michael M. (anfaenger2011)


Lesenswert?

> Stefan B. schrieb:
>> Lies dir die Doku von RCALL vs. RJMP mal

Dazu meinte ich eigentlich den passenden Link.

Gruss Micha

von Karl H. (kbuchegg)


Lesenswert?

Michael Müller schrieb:
>> Stefan B. schrieb:
>>> Lies dir die Doku von RCALL vs. RJMP mal
>
> Dazu meinte ich eigentlich den passenden Link.

Das hat doch keinen Sinn.

Es gibt keinen Link zu RCALL oder RJMP.
Beides sind Befehle, die ein AVR versteht.
Und beide sind natürlich im Instruction Set beschrieben.
Drück doch mal in deinem AVR-Studio die Taste F1. AUch dort findest du 
dann die Doku über alle Assembler-Befehle wieder.

Und beide werden bei Durcharbeit des AVR-Tutorial (merkst du was? Das 
ist jetzt sicher schon das 5te mal, dass das Tut in diesem Thread 
erwähnt wird)
an sinnvollen Stellen eingeführt und auch was es damit auf sich hat, wie 
man sie verwendet, welche Voraussetzungen vorliegen müssen (RCALL) und 
wie es dann weiter geht.

Es hat keinen Sinn, sich einzelne Befehle rauszupicken und von diesen 
alles wissen zu wollen. Programmieren und ganz besonders 
Assembler-Programmieren ist wie Schach spielen: Die Mächtigkeit und 
Komplexität kommt nicht daher, dass man weiß wie die Figuren ziehen. Die 
Mächtigkeit entsteht dadurch, dass man weiß, wie man Figuren und 
Zugfolgen kombinieren kann.

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.