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
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]])
Ein weiterer Fehler ist, dass du deinen µC komplett unterschätzt, was
Speed angeht.
Das hier
1
ldir16,0x02;
2
rcallzeitschleife;// Pause
3
4
....
5
6
zeitschleife:
7
decr16;
8
brnezeitschleife;
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.
@ 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.
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
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
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.
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.
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:
> 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.
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
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
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".
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!
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.
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
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.
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.