Hallo zusammen,
ich habe das Problem, das der Attiny26-16 den rcall Befehl nicht mag, er
bleibt da immer hängen. Ich benutze AtmelStudio 6.0 und schreibe in asm.
Das Programm läuft ohne Probleme auf dem ATtiny13-20 mit rcall. Wenn ich
die Unterprogramme ins Hauptprogramm hole, läuft auch der ATtiny26.
Die inc. Datei habe ich natürlich umgestellt. Programmieren läst sich
der ATtiny 26 ohne probleme. Keine Fehlermeldung.
Hoffe es kann mir bei diesem Problem jemand weiterhelfen.
l.g. Achim
Walter S. schrieb:> ohne Programm sicher nicht
Doch, der Tiny13 initialisiert seinen Stackpointer per Hardware beim
Reset, beim Tiny26 muss man den Stackpointer von Hand initialisieren.
Achim schrieb:> Wenn ich> die Unterprogramme ins Hauptprogramm hole, läuft auch der ATtiny26.
Eben, das deutet darauf hin, dass der Stackpointer nicht initialisiert
ist...
...
Den Befehl gibt es, geht auch wenn ich ihn nur ein mal aufrufe, aber
beim zweiten mal aus einem billigen Blikprogramm mit zwei LED bleib er
stehen.
.include "tn26def.inc"
rjmp Anfang
Anfang:
ldi r16,0xff
out ddra,r16
ldi r16,0x18
out ddrb,r16
Schleife:
ldi r16,0x10
out portb,r16
;Warte:
ldi r17,255
Warte1:
ldi r18,255
Warte2:
dec r18
brne Warte2
dec r17
brne Warte1
;ret ;Rücksprung
;rcall Warte
ldi r16,0x0
out portb,r16
;Pause:
ldi r17,255
Pause1:
ldi r18,255
Pause2:
dec r18
brne Pause2
dec r17
brne Pause1
;ret ;Rücksprung
;rcall Pause
ldi r16,0x8
out portb,r16
;Warte:
ldi r17,255
Warte3:
ldi r18,255
Warte4:
dec r18
brne Warte4
dec r17
brne Warte3
;ret ;Rücksprung
;rcall Warte
ldi r16,0x0
out portb,r16
;Pause:
ldi r17,255
Pause3:
ldi r18,255
Pause4:
dec r18
brne Pause4
dec r17
brne Pause3
;ret ;Rücksprung
;rcall Pause
rjmp Schleife
Hallo Hannes, könnten Sie mir das bitte als asm vorschreiben, da ich
nicht weiß, was SPL, SPH und Ramend ist. Ich übe erst seit zwei Wochen
mit dem ATtiny13, doch da geht es super. Mir haben nur die ein und
Ausgänge nicht gereicht.
l.g. Achim
Danke Spess53, werde ich mal so probieren. Das ganze soll mal eine
Schrittmotorsteuerung werden, wenns fertig ist. Mit 3 ATtiny13 geht es
schon.
l.g. Achim
Achim schrieb:> könnten Sie mir das bitte als asm vorschreiben,
Hat Spess bereits gemacht.
> da ich nicht weiß, was SPL, SPH und Ramend ist.
Dann könnte man diese Begriffe als Suchbegriffe im Datenblatt-PDF
benutzen.
...
Werde es auf jeden fall nachlesen, will ja wissen was die Befehle
machen.
Ich danke euch beiden für eure Hilfe.
PS: Bin Modellbauer, Eisenbahn, Spur Z, 46Jahre.
Achim schrieb:> Bin Modellbauer, Eisenbahn, Spur Z,
Ich mag's ein bissel größer, beschränke mich aber mehr auf die
Elektronik und Elektrik, mit dem Bauen von Modellen habe ich es nicht
so...
http://www.hanneslux.de/ Da findest Du vielleicht ein paar nützliche
Tipps betreffs Einstieg in AVR-Assembler.
> 46Jahre.
Das war ein schönes Alter, ist aber schon verdammt lange her... ;-)
...
he...was soll ich denn erst sagen mit meine 78 Jahre!
Spur H0 Fleischmann mit Roco kombiniert.
Anlage voll elektronisch ausgerüstet mit uralten ATARI in GFA-Basic.
Zwei Tiny2313 steuern einen Märklin-Kran und Container-Kran von Brawa.
Interessant, was Achim da vorzeigt.
Grüße
Rolf
Hallo Achim,
ich habe mir nochmal Deinen Quelltext angeschaut, und da ist mir
was merkwürdiges aufgefallen.
im Anfang
ldi r16,0x18 ;0b0001 1000
out ddrb,r16 ;also PORTB,PB4 + PB3 = Output
in der Schleife kommt nach dem zweiten rcall
ldi r16,0x8 ;das wäre 0b1000 0000
out portb,r16
aber Du hast doch im Anfang im Datenrichtungs-Register PB7
garnicht als Output gesetzt, oder?
Evtl. kann auch ich einen Denkfehler haben!
Grüße
Rolf
Rolf H. schrieb:> ldi r16,0x8 ;das wäre 0b1000 0000
No.
Genau lesen. Da ist eine führende 0 nicht geschrieben worden.
0x8 ist dasselbe wie
0x08
Und gerade bei Hex-Zahlen (oder auch Binärzahlen) die eine starke
Affinität zur Bitdarstellung haben, ist es unklug, führende 0-en
wegzulassen. Führt auf lange Sicht praktisch immer zu derartigen
Missverständnissen. An dieser Stelle ist es besser die führenden 0-en zu
schreiben und so wieder in das 8-Bit Schema zu kommen, welches zentral
für die Arbeit auf Bitebene ist.
Nicht alles, was technisch erlaubt ist, ist programmiertaktisch
sinnvoll.
Noch besser wäre es allerdings, das ganze so zu schreiben
ldi r16, (1<<PB4) | (1<<PB3)
out ddrb,r16
bzw.
ldi r16, (1<<PB4)
out portb,r16
Denn jetzt stehen die Bitnamen direkt dort und kein Mensch muss mehr
überlegen, welche Bits sich eigentlich hinter 0x18 bzw. 0x8 verstecken.
Karl Heinz Buchegger schrieb:> Noch besser wäre es allerdings, das ganze so zu schreiben>> ldi r16, (1<<PB4) | (1<<PB3)> out ddrb,r16>>> bzw.>> ldi r16, (1<<PB4)> out portb,r16
Und noch besser ist es direkt sprechende Namen zu verwenden.
ldi r16, SIGNAL1
Helmut Lenzen schrieb:> Und noch besser ist es direkt sprechende Namen zu verwenden.>> ldi r16, SIGNAL1
Absolut.
Und die Moral von der Geschichte:
Man kann alleine durch unterschiedliche Schreibweisen steuern, wie gut
oder schlecht ein Code zu lesen bzw. zu verstehen ist. Und das sogar mit
relativ wenig Aufwand, der einen riesen Unterschied ausmachen kann.
Karl Heinz Buchegger schrieb:> ldi r16, (1<<PB4)>> out portb,r16
Hast Recht Karl Heinz Buchegger, das werde ich mir mal angewöhnen.
Wieder was gelernt!
Grüße
Rolf
Karl Heinz Buchegger schrieb:>> Und noch besser ist es direkt sprechende Namen zu verwenden.>>>>>> ldi r16, SIGNAL1
dann muß ich aber doch am Anfang PB4 als SIGNAL1 definieren.
Macht man das mit .equ PB4=SIGNAL
Rolf H. schrieb:> Karl Heinz Buchegger schrieb:>>> Und noch besser ist es direkt sprechende Namen zu verwenden.>>>>>>>>>> ldi r16, SIGNAL1>>> dann muß ich aber doch am Anfang PB4 als SIGNAL1 definieren.
Ja und?
Spätestens wenn die LED wegen Hardware Problemen vom Pin PB4 auf PB2
'umziehen' muss, bist du froh drüber, wenn du nur an einer Stelle die
neue Belegung einträgst und nicht quer durch das ganze Programm hirschen
und alle relevanten Hex-Zahlen finden und anpassen musst.
> Macht man das mit .equ PB4=SIGNAL
fast
a) anders rum. In den meisten Programmiersprachen steht immer links
vom = das Ergebnis und rechts davon, wie man zu diesem Ergebnis
kommt.
b) so wie das verwendet wird, muss da stehen
.equ SIGNAL1 = (1<<PB4)
Nur dann ist
ldi r16, (1<<PB4)
und
ldi r16, SIGNAL1
auch gleichwertig.
Karl Heinz Buchegger schrieb:> ldi r16, (1<<PB4)>> out portb,r16
richtig wäre es aber wenn:
ldi r16,0x8 ;0x08 = 0b0000 1000
out portb,r16
ldi r16, (1<<PB3) ;oder hab ich wieder nen Denkfehler?
Grüße
Rolf
Rolf H. schrieb:> Karl Heinz Buchegger schrieb:>> ldi r16, (1<<PB4)>>>> out portb,r16>> richtig wäre es aber wenn:>> ldi r16,0x8 ;0x08 = 0b0000 1000> out portb,r16>>> ldi r16, (1<<PB3) ;oder hab ich wieder nen Denkfehler?
Ne. stimmt schon.
Ich hab jetzt nicht auf die Pin-Nummern geachtet.
Vergleich mal mit
1
.include "tn26def.inc"
2
3
.equ LED_PORT = PORTB
4
.equ LED_DDR = DDRB
5
6
.equ LEFT_LED = (1<<PB4)
7
.equ RIGHT_LED = (1<<PB3)
8
9
rjmp Anfang
10
11
Anfang:
12
ldi r16,low(Ramend)
13
out sp,r16
14
15
ldi r16, LEFT_LED | RIGHT_LED
16
out LED_DDR, r16
17
18
Main:
19
ldi r16, LEFT_LED
20
out LED_PORT, r16
21
rcall Warte
22
ldi r16, 0x0
23
out LED_PORT, r16
24
rcall Warte
25
ldi r16, RIGHT_LED
26
out LED_PORT, r16
27
rcall Warte
28
ldi r16, 0x0
29
out LED_PORT, r16
30
rcall Warte
31
rjmp Main
32
33
Warte:
34
ldi r17,255
35
Warte1:
36
ldi r18,255
37
Warte2:
38
dec r18
39
brne Warte2
40
dec r17
41
brne Warte1
42
ret
Spielt es jetzt wirklich noch eine große Rolle, wo die LDE angeschlossen
ist?
Nicht wirklich. Wenn die eine LED (sagen wir mal die rechte) nicht an
PB3 angeschlossen ist, sondern an PB2, dann änder ich einfach
1
...
2
.equ RIGHT_LED = (1<<PB2)
3
...
und fertig. Den Rest der Programmanpassung macht der Assembler.
Und das ist noch lange nicht alles, was man in diesem Programm
verbessern kann. Zb. sollten einem die 'Komplett'-Zugriffe auf den Port
ein Dorn im Auge sein. Mittels
1
ldi r16, LEFT_LED
2
out LED_PORT, r16
verändert man ja nicht nur den einen Pin, sondern alle anderen Pins
gleich mit! Solange man nur 1 oder 2 LED an einem Port hat, mag das ja
noch angehen. Aber wenn du 3 LED, 2 Summer, und 3 Taster am Port hängen,
dann wirds aufwändig, das immer alles im Kopf zu behalten, welcher Pin
jetzt gerade wie stehen muss und welchen Wert man daher an das
Port-Register zuweisen muss, damit wieder alles stimmt.
Genau aus dem Grund gibt es die SBI und CBI Instruktionen, mit denen man
tatsächlich nur 1 Bit und nicht mehr manipuliert.
1
.include "tn26def.inc"
2
3
.equ LED_PORT = PORTB
4
.equ LED_DDR = DDRB
5
6
.equ LEFT_LED = PB4
7
.equ RIGHT_LED = PB3
8
9
rjmp Anfang
10
11
Anfang:
12
ldi r16,low(Ramend)
13
out sp,r16
14
15
ldi r16, (1<<LEFT_LED) | (1<<RIGHT_LED)
16
out LED_DDR, r16
17
18
Main:
19
sbi LED_PORT, LEFT_LED
20
rcall Warte
21
cbi LED_PORT, LEFT_LED
22
rcall Warte
23
24
sbi LED_PORT, RIGHT_LED
25
rcall Warte
26
cbi LED_PORT, RIGHT_LED
27
rcall Warte
28
29
rjmp Main
30
31
Warte:
32
ldi r17,255
33
Warte1:
34
ldi r18,255
35
Warte2:
36
dec r18
37
brne Warte2
38
dec r17
39
brne Warte1
40
ret
Aber: All das steht ja auch mehr oder weniger im
AVR-Tutorial
Wenn auch nicht in den Feinheiten von Anfang an.