Hallo alle zusammen,
ich bin seid einiger Zeit ein stiller Mitleser und konnte bisher kleine
Assemblerprogramme mit euer Hilfe und des Tutorials fehlerfrei
schreiben.
Jetzt bin ich mit meinem Latein am Ende.
Ich möchte mit einem kleinen Taster eine Kreislauf starten.
Wenn der Taster S1 (PB2) betätig wird, soll eine grüne LED (PB4) kurz
aufleuchten, um zu zeigen, dass der Kontakt vom Taster (PB2) erkannt
wurde. Dabei soll das Programm kurzzeitig stehen bleiben (Delay) und
dann weiter arbeiten. Als nächstes soll die rote LED (PB0) eingeschaltet
werden und gleichzeitig geht die grüne LED aus (wenn kein Kontakt über
den Taster erkannt wurde).
Die rote LED bleibt so lange eingeschaltet, bis ein weiterer Impuls über
den Taster eingegangen ist.
Dann beginnt der Zyklus von vorn.
Ich verwende einen ATtiny13 und ein kleines Board aus einem Lernpaket.
Mein Problem, wenn ich das Programm im AmtelStudio 6 durchlaufen lasse,
läuft es ohne Probleme. Sobald ich es in den uC lade leuchtet die grüne
LED nach ein paar Impulsen dauerhaft und nach ein paar weiteren,
schaltet der uC auf die rote LED um und das wars. Nix funktioniert mehr.
Über eure Hilfe bin ich sehr dankbar :-)
1
.include "tn13def.inc"
2
rjmp anf
3
anf:
4
.def zustand =r17
5
ldi r16, (1<<PB2) ; PB2 an PinB aktivieren
6
out portb, r16 ; der Port auf Eingang gestellt ist.
7
8
9
ledgruen:
10
clr r16
11
in r16, pinb ; an Port b anliegende Werte (Taster) nach r16 einlesen
12
cpi r16, 0x00 ;0 = kein Signal liegt an
13
breq ledgruen
14
cpi r16, 0x10 ; Signal von LED - Grün - möglicher Zustand laut Simulator
15
breq ledgruen
16
cpi r16, 0x11 ; Signal von LED - Rot und LED - Grün - möglicher Zustand laut Simulator
17
breq ledgruen
18
rjmp noteq
19
20
rjmp ledgruen ; zu "loop:" -> Endlosschleife
21
noteq:
22
ldi r16, (1<<PB4)
23
ldi r18, (1<<DDB4)
24
out ddrb, r16 ; PB4 Ausgang low
25
out portb, r18 ; PB4 Ausgang high = LED Grün Ein
26
clr r16
27
rcall DLY1 ; Verhinderung einer Signalüberschneidung durch den Taster
28
rjmp zt_kontrolle
29
rjmp ledgruen
30
31
zt_kontrolle:
32
cpi zustand,0 ;Vergleiche den Gespeicherten Zustand mit 1(=EIN)
33
brne LEDrotAus ;Wenn Zustand = 1, dann springe zu LEDrotAus
34
ldi zustand,1 ;Wenn Zustand ungleich 1 ist, dann lade in Zustand den Wert 1
35
ldi r16, (1<<PB0)|(0<<PB4)
36
ldi r18, (1<<DDB0)|(0<<DDB0)
37
out ddrb, r16 ;PB0 als Ausgang setzen (Low) PB4 wird als Eingang gesetzt
38
out portb, r18 ;Rote LED ein (High) PB4 - Tri State
39
rjmp ledgruen
40
LEDrotAus:
41
clr zustand ;Zustand löschen (=0)
42
ldi r16, (0<<PB0)|(0<<PB4)
43
ldi r18, (0<<DDB0)|(0<<DDB4)
44
out ddrb, r16 ;PB0 als Ausgang löschen
45
out portb, r18 ;Rote LED aus - Tri - State
46
rjmp ledgruen
47
48
DLY1: ; Warteschleife ca. 0,5 - 1 sec
49
ldi r16, 250
50
DLY2:
51
ldi r17, 250
52
DLY3:
53
ldi r18, 5
54
DLY4:
55
dec r18
56
brne DLY4
57
dec r17
58
brne DLY3
59
dec r16
60
brne DLY2
61
ret
Oder
1
ledgruen:
2
in r16, pinb ; an Port b anliegende Werte (Taster) nach r16 einlesen
3
cpi r16, 0x04 ; Wert bei Eingang vom Taster
4
breq noteq
5
cpi r16, 0x15 ; Wert bei Eingang vom Taster und den LED's
Zwei (von vielleicht mehr) Punkten:
1) Den Pull-Up an PB2 schaltest du im Verlauf des Programms wieder aus.
2) Du vergleichst immer den kompletten Port-Inhalt, obwohl dich doch nur
eine einzelnes Bit interessiert.
Ganz allgemein ist für dich jetzt also der Zeitpunkt gekommen, wo du
dich ganz dringend damit beschäftigen musst, wie man Aktionen auf nur
einzelne Bits beschränkt, sowohl beim Output (Punkt 1), als auch beim
Input (Punkt 2).
Bernd schrieb:> ldi r16, (1<<PB2) ; PB2 an PinB aktivieren> out portb, r16 ; der Port auf Eingang gestellt ist.
Ich verstehe Deine Kommentare nicht so ganz.
Nach einem Reset werden ja alle " Special Functions Register " ( SFR ),
mit einem bestimmten Wert vorinitialsiert. Beim Data Direction Register
PortB ( DDRB ) geschieht dies mit einem Nullbyte, also alle Bits = 0.
Das bedeutet mit den beiden oberen Befehlszeilen aktivierst Du den
Portpin B2, als Eingang mit internen Pullup. Bzw. als Eingang werden sie
ja schon durch die Reset-Initialisierung eingestellt. Du schaltetst mit
den beiden Befehlen nun den Pullup an den Eingangspin PB2. Dies wolltest
Du sicherlich auch - nur aus deinem Kommentaren geht das nicht klar
hervor.
Soweit so gut. Den Rest kann ich mir hoffentlich am Montag näher
anschauen.
Nur so als Tipp. Taster prellen. Und µC arbeiten meistens rasend schnell
- der Simulator nicht.
Bernd_Stein
Mir erscheint das Ganze, als wär’s fast ausschließlich mittels Copy und
Paste entstanden.
Ich weiß: Heuzutage geht Kopieren über Studieren - ob das aber richtige
Weg ist, darf bezweifelt werden.
Gerade die Differenzen zwischen Aktion und Kommentar sind ein recht
guter Hinweis darauf. Auch habe ich es noch nie gesehen, dass jemand ein
Register (r17) mit einem Namen versieht, alle andren aber nicht. Ich
kenne nur ent- oder weder.
Wobei man sich trefflich über den Nutzen des einen oder den Nachteil des
anderen streiten kann.
Vielleicht solltest Du etwas mehr Zeit in "Wie geht's" und weniger in
"Wo steht's" investieren.
Woah, das sind schon mal schnell viele Antworten.
zu Stefan Ernst:
1.Das ich den Pullup an PB2 ausgeschaltet habe, ist mir gar nicht
aufgefallen, ich habe mich immer nur auf die Zustände meiner LED's
konzentriert. Ich habe jetzt in jeder Zeile, die portb bearbeitet mit
"|(1<<PB2)" erweitert.
Der Pullup bleibt nun dauerhaft an.
2.Da bin ich gerade dabei mich einzumummeln, ist mir gelungen, einzelne
Bits zu manipulieren aber die direkte Abfrage halt nicht. Deshalb habe
ich über die summen der einzelnen Bits gearbeitet.
Danke für deine Tipps.
Beim kurzen Überfliegen, denke ich werde ich mich mit sbrc, sbis und die
Möglichkeiten von andi genauer angucken.
Zu der alte Hanns:
Da hast du Recht. Es ist im Simulator nicht aufgefallen, da ich beim
Debuggen immer die Schleife ausgestellt habe. Neues Register, Problem
behoben. Danke :-)
Zu Bern_Stein.
Ja, die Kommentare sind noch ausbaufähig :-)
Ich habe mir im Netz verschiedene Herangehensweisen angeguckt, wie ich
einen Taster entprellen kann. Die Herangehensweisen waren einleuchtend,
nur an der Umsetzung bin ich bisher nicht vorrangekommen und mein
Gedanke war, dass sobald am Taster ein Signal kommt, egal wie oft, soll
das Programm anfangen zu arbeiten und auf jeden Fall immer einmal die
Schleife durchlaufen. Da nun mehrere Impulse an PB2 ankommen, wird so
nur der erste gewertet und erst nach "rjmp ledgruen" wird die nächste
Abfrage gestellt.
Dass das nicht das Gelbe vom Ei ist, weiß ich. Nur sind meine
Assemblerkenntnisse nicht genug ausgereift, um ihn noch zu entprellen.
Das war mein nächster Schritt. Ich wollte jetzt die Struktur des
Hauptprogrammes aufbauen.
Zu Amateur:
Ich arbeite mich durch das AVR - Tutorial und das kleine Heft des
Experimeniersets. Beide haben eins gemeinsam, die Formatierung und auch
Schreibweisen. In beiden wird auch per Quellcode erklärt. Ich kann dir
aber sagen, dass ich mir für bei diesem Quellcode an die Atmel Libary
Home und dem Datasheet gehalten habe, als nach der Copy und Paste
Methode vorzugehen.
Das war am Anfang (bei meinem aller ersten Versuch) meine Strategie, die
ich schnell verworfen, nachdem ich erkannt habe, wie umfangreich die
Thematik mit dem uC ist.
Es stimmt, dass das "Wie" wichtiger ist als das "Wo". Nur bin ich jetzt
auch nicht weitergekommen und habe mich an das Forum gewandt, damit mir
hier geholfen wird. Ich erwarte nicht, dass mir jemand meinen Code
korrigiert und für mich schreibt. Das will ich selber nicht, denn dann
lerne ich es ja nichts. Aber das Hinweise gegeben werden, was ich falsch
gemacht habe oder wo ich nochmal was nachlesen sollte, das erhoffe ich
mir hier.
An alle:
Ich habe mir mein fertiges Programm in mehrere kleine Aufgaben geteilt,
sodass ich immer wieder eine neue Eigenheit habe. Nun war ich soweit,
dass ich einen nicht entprellten Taster hatte, der mit einer LED lief,
die Ansteuerung einer zweiten led, eine endlos & endende blinkschleife
und letztes jeweils mit einem Taster gekoppelt.
Diese Puzzelt eile wollte ich jetzt zu einer kleinen Grundstruktur
zusammensetzen.
Danke für eure Beiträge.
Bin mal gespannt, was noch dazukommt und morgen werde ich weiter lesen,
programmieren und euch berichten, wie ich vorangekommen bin.
In diesem Sinne gute Nacht. :-)
der alte Hanns schrieb:> SPL wird hardwaremäßig mit RAMEND = 0x009f initialisiert.
Wo hast Du das gelesen? In jedem Datenblatt und auch in den App-Notes
wird darauf hingewiesen, dass der Stack initialisiert werden soll/muss.
Würde mich wirklich interessieren wo das geschrieben steht, denn ich
lerne gerne immer noch etwas dazu.
Grüße
Rush schrieb:> Wo hast Du das gelesen? In jedem Datenblatt und auch in den App-Notes> wird darauf hingewiesen, dass der Stack initialisiert werden soll/muss.
Wann hast du das letzte Mal ein AVR-Datenblatt gelesen?
Alle neueren AVRs intialisieren ihren Stack selber sinnvoll, also auf's
Ende des vorhandenen RAM.