Hallo,
habe ein Problem mit einer Multiplex Ansteuerung.
Möchte folgendes machen:
Eine Siebensegment Anzeige, die durch einen Latch (74HC573), die Zahlen
0 bis 9 hochzählen soll.
Die Zahlen sind ind einer Tabelle in Hex-Form gespeichert.
Jetzt will ich diese Auslesen und zur Anzeigen bringen.
Vor dem Schreiben soll das Latch auf High gesetzt werden danach wieder
auf Low.
Bekomme aber nur die Null zur Anzeige.
Was mache ich nur falsch?
Habe mir schon die Zähne an der Tastatur ausgebissen.
Anbei noch das Programm:
.device AT90s8515
.include "C:\Programme\Atmel\AVR Studio\Appnotes\8515def.inc"
;Definition der Steuerleitungen
.equ sek_ein = PA7 ; Sekunden Einer
.equ sek_zen = PA6 ; Sekunden Zehner
.equ min_ein = PA5 ; Minuten Einer
.equ min_zen = PA4 ; Minuten Zehner
.equ stu_ein = PA3 ; Stunden Einer
.equ stu_zen = PA2 ; Stunden Zehner
; Variablendefinition
.def zeichen = r0 ; Zeichen aus Tabelle
.def counter = r17 ; Zaehler für die Anzeige
.def temp = r18
.def buffer = r19
.def delay = r20
.def delay1 = r21
.CSEG
.ORG 0x00 ; Programm beginnt bei 0
rjmp main ; Starte Hauptprogramm
init: cli
ldi temp,0b1111111
out DDRA,temp
ret
write_data:
ldi temp,0b11111111
out DDRB,temp
cbi porta,sek_ein
out PORTB,buffer
sbi porta,sek_ein
ret
main: ldi temp,RAMEND
out SPL,temp
rcall init
ldi ZL,LOW(tabelle*2)
ldi ZH,HIGH(tabelle*2)
ldi counter,10
loop_msg1: lpm
mov buffer,zeichen
rcall write_data
inc ZL
brcc no_carry1
inc ZH
no_carry1: dec counter
brne loop_msg1
loop: rjmp loop
; Ziffern 0 1 2 3 4 5 6 7 8 9
Tabelle: .db 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
Danke im voraus
Michael T
Hi!
cbi setzt Ausgang auf 0 = Low
Ausgabe
sbi setzt Ausgang auf 1 = High
Wolltest du es nicht andersrum??
Eine Verzögerung der Ausgabe vermisse ich ebenfalls, du wirst
bestenfalls eine 9 sehen. Beachte auch die Flag's im Datasheet. Bei inc
steht da Z,N,V. ADIW ist also völlig richtig.
viel Erfolg
Uwe
Oder ums noch deutlicher zu machen:
> Du darfst nix "rcall"en bevor der Stackpointer gesetzt ist!
heißt auch, daß der Stackpointer nicht richtig initialisiert wird. Der
besteht beim 8515 nämlich aus SPH und SPL. Aber das ist wohl nicht der
Grund für das Versagen des Programms. Das wird eher mit dem mehrfach
erwähnten inc/adiw zusammenhängen.
Schmittchen.
Öhm, was ich über den SP geschrieben habe vergeßt mal bitte wieder. Ich
habe mir eingeildet das "rcall init" käme vor der Initialisierung des
Stackpointers.
Aber dass der Stack nicht richtig initialisiert ist stimmt natürlich,
siehe Tutorial #3.
Habe ich alles probiert.
Mit dem "rcall"en, habe mich schon gewundert.
Das Programm geht in der Simulation wunderbar.
Doch bleibt es im Avr irgendwo hängen.
Habe ich vieleicht was übersehen.
Viele Grüße
Michael T
Jetzt geht es!
.include "C:\Programme\Atmel\AVR Studio\Appnotes\8515def.inc"
.def zeichen = r0
.def buffer = r16
.def counter = r17
.def delay =r18
.def delay1 =r19
.def temp = r20
.equ sek_ein = pa7
.CSEG
.ORG 0x0000
rjmp main
init: ldi temp,0b11111111 ;
out ddra,temp ;PORTA ist Ausgang
out ddrb,temp ;PORTB ist Ausgang
ret
output: sbi porta,sek_ein ;spreche Anzeige an
out portb,buffer ;sende Daten
cbi porta,sek_ein ;disable Anzeige
rcall dly ;springe zur Pause
ret
dly: dec delay
brne dly
dec delay1
brne dly
ret
main: ldi temp,LOW(ramend) ; Oberes Byte
out SPL,temp ; an Stapelzeiger
ldi temp,HIGH(ramend) ; Unteres Byte
out SPH,temp ; an Stapelzeiger
rcall init
Loop0: ldi counter,10 ;Zaehler für Zeichen
ldi ZL,LOW(Tabelle*2) ;Low-Zeiger auf Tabellenanfang
ldi ZH,HIGH(Tabelle*2) ;High-Zeiger auf Tabellenanfang
loop1: lpm ;hole Zeichen aus Tabelle
mov buffer,zeichen ;Zeichen uebergeben
rcall output ;schreibe Zeichen in Anzeige
adiw ZL,1 ;16-Bit Pointer um 1 erhoehn
nocarry: dec counter ;alle Zeichen gesendet?
brne loop1 ;Nein! Sende naechstes Zeichen
loop: rjmp main ;Programm wird neu gestartet
; Ziffern 0 1 2 3 4 5 6 7 8 9
Tabelle: .db 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
Habe jetzt adiw genommen, aber mit "inc ZL" und "inc ZH" geht es auch.
Nur was ist jetzt der unterschied vom Stackpointer bei:
ldi temp, LOW(ramend) ; Oberes Byte
out SPL,temp ; an Stapelzeiger
ldi temp,HIGH(ramend) ; Unteres Byte
out SPH,temp ; an Stapelzeiger
zu: ldi temp,RAMEND
out SPL,temp
Weiss einer dazu die Antwort?
Gruß
Michael T
Wie meinen? Na einmal belegst du nur SPL mit einem Wert, das andere Mal
SPL und SPH!
SPH steht nach dem Einschalten auf 0x00, und das ist schon was anderes
als 0x02, damit steht im ersten (richtigen) Fall der Stackpointer auf
0x025F, in deinem zweiten (nicht funktionierenden) Fall auf 0x005F.
Irgendwann läuft dir da dann was rein.
RAMEND = 0x025F
HIGH(RAMEND) = 0x02
LOW(RAMEND) = 0x5F
Schmittchen.