PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Binär Uhr - Zehnerstellen...



handwerker
11.09.2008, 21:29
Ich bin gerade dabei eine binär-uhr zu basteln.
ich benutze einen atmega16 und habe an den porta die sekunden, portb die minuten und c die stunden.
die uhr läuft soweit ganz gut und auch ordentlich.
Bis:
Die Leds werdem einzeln angesteuert.
Mein Problem ist, wie kann ich es jetzt umsetzen, dass in der 2.reihe die zehnersekunden angezeigt werden?

also so:


| O
O | O
O | O
O | O
10er | 1er


grüße,
ein handwerker

fhs
12.09.2008, 07:59
Hallo handwerker,

wenn ich Deine Frage richtig verstehe, zeigst Du zur Zeit 8-Bit Binärwerte an, möchtest diese aber lieber als BCD-Werte darstellen. Dann brauchst Du eine kleine Routine, die Dir Binärwerte<60 in BCD (Zehnerstelle höherwertiges Nibble, Einerstelle niederwertiges Nibble) umwandelt.
Das könnte man ganz primitiv durch mehrfache Subtraktion von 10 lösen:

; r16 enthält Binärwert <60
; r17 wird als Zehner-Zähler verwendet
; Ergebnis in r16: Zehner-Stelle b4-b7, Einerstelle b0-b3

to_bcd:
ser r17 ; Zehner-Zähler = -1
bcd_lp:
inc r17 ; ++Zehner-Zähler
subi r16, 10 ; -10
brpl bcd_lp ; noch einmal, wenn >=0

swap r17 ; Zehnerstellen: b4-b7
subi r16,-10 ; letzte Subtraktion rückgängig machen
or r16,r17 ; Einerstellen: b0-b3

Habe ich schnell mal so hingeschrieben -- ist sicher noch optimierbar; wobei die Optimierung für eine Uhr aber wohl eher unkritisch ist.

Gruß

Fred

handwerker
14.09.2008, 12:15
genauso meine ich das.
entweder bin ich zu blöde, nur funktioniert es nicht so, wie ich das denke.
ich habe das jetzt so eingebaut.



sekunde:
cpi sekunde, 60
breq minute
cpi sekunde, 10
brsh bcd
out ddra, sekunde
rjmp sekunde


bcd:
ser sekunde2

to_bcd:
inc sekunde2
subi sekunde, -10
brpl to_bcd
swap sekunde2
subi sekunde, -10
or sekunde, sekunde2
out ddra, sekunde
rjmp sekunde

fhs
14.09.2008, 13:51
Hi,

Du kannst die Konversionsroutine für die Sekunden, Minuten und Stunden nutzen. Ich würde die Konversion in ein Unterprogramm packen (mit RCALL anspringen und mit RET verlassen).
Der in die Konversionsroutine gehende Wert darf <=10 sein; ein vorheriges Testen (Deine Zeile "cpi sekunde, 10") ist nicht nötig.
Du verwendest "sekunde" sowohl als Label als auch als Namen eines Registers. Welcher Assembler kann damit umgehen?

Gruß

Fred

handwerker
14.09.2008, 15:46
okay, das habe ich jetzt gemacht. nur leuchten dann jetzt alle leds für die sekunden. bis auf die erste, die blinkt im sekundentakt.
ich nutze avr studio und es hat deswegen nicht rumgemeckert.
habe mal die label geändert, daran scheint es aber nicht zu liegen.
*grübel*




sekunden:
cpi sekunde, 60
breq minuten
rcall bcd
out ddra, sekunde
rjmp sekunden


bcd:
ser sekunde2
to_bcd:
inc sekunde2
subi sekunde, -10
brpl to_bcd
swap sekunde2
subi sekunde, -10
or sekunde, sekunde2
ret

fhs
14.09.2008, 16:00
Hi,

zur Fehlersuche musst Du schon mehr Code posten. Nimm doch einfach mal einen festen Wert für die Sekunden, um die BCD-Darstellung zu testen. Meine Konversionsroutine funktioniert im AVRStudio-Simulator problemlos. Wird "sekunde2" anderswo (z.B. in einer Interrupt Service Routine) mibenutzt? Wie schaltest Du die Zeit weiter?
Statt "out DDRA, register" willst Du sicher "out PORTA, register" schreiben!

Gruß

Fred

handwerker
14.09.2008, 16:54
uffz...
sekunde2 wird nur in der bcd-routine genutzt, ansonsten gar nicht.

also insgesamt sieht es so aus:



.nolist
.include"m16def.inc"

.equ xtal = 8000000
.equ debounce = 256
.equ remainder = xtal - xtal / debounce * debounce

.def isreg = r15
.def wr0 = r16
.def iwr0 = r17
.def prescaler = r18

.def sekunde = r19
.def sekunde2 = r20
.def minute = r21
.def stunde = r22

.list
rjmp init
.org OC1Aaddr
rjmp OC1Aint
;-------------------------------------------------------------------------
OC1Aint:
in isreg, sreg

ldi iwr0, high( xtal / debounce - 1 )
out ocr1ah, iwr0
ldi iwr0, low( xtal / debounce - 1 )
out ocr1al, iwr0

dec prescaler
brne _oci1

ldi prescaler, debounce
inc sekunde

ldi iwr0, high( xtal / debounce + remainder - 1 )
out ocr1ah, iwr0
ldi iwr0, low( xtal / debounce + remainder - 1 )
out ocr1al, iwr0
_oci1:
out sreg, isreg
reti
;-------------------------------------------------------------------------
init:
ldi wr0, 0x0
out ddra, wr0
out ddrb, wr0
out ddrc, wr0
ldi sekunde, 0


ldi wr0, high( ramend )
out sph, wr0
ldi wr0, low( ramend )
out spl, wr0

ldi wr0, 1<<WGM12^1<<CS10
out TCCR1B, wr0

ldi wr0, high( xtal / debounce - 1 )
out ocr1ah, wr0
ldi wr0, low( xtal / debounce - 1 )
out ocr1al, wr0
out tcnt1l, wr0
ldi prescaler, debounce

ldi wr0, 1<<OCIE1A
out TIMSK, wr0
sei




main:
ldi sekunde, 0

sekunden:
cpi sekunde, 60
breq minuten
rcall bcd
out ddra, sekunde
rjmp sekunden


bcd:
ser sekunde2
to_bcd:
inc sekunde2
subi sekunde, -10
brpl to_bcd
swap sekunde2
subi sekunde, -10
or sekunde, sekunde2
ret



minuten:
inc minute
cpi minute, 60
breq stunden
out ddrb, minute
rjmp main



stunden:
ldi minute, 0
out ddrb, minute
inc stunde
cpi stunde, 24
breq tag
out ddrc, stunde
rjmp main


tag:
ldi stunde, 0
out ddrc, stunde
rjmp main

fhs
14.09.2008, 16:58
Hi,

lies noch einmal meinen letzten Satz im letzten Posting. Falls es dann noch nicht klappt, sehe ich mir mal Deinen kompletten Code an.

Gruß

Fred

PS: Auch bei den Minuten und Stunden musst Du DDRx durch PORTx ersetzen!

handwerker
14.09.2008, 17:12
Nein, mit PortA funktioniert es nicht.
Ich habe den beispielcode genutzt.
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC#Beispiel_in_Assembler

fhs
14.09.2008, 17:18
Hi,


Nein, mit PortA funktioniert es nicht. ...
obwohl Du in Deinem ersten Posting schreibst:
...die uhr läuft soweit ganz gut und auch ordentlich?

Sieh Dir mal genau Deine Intialisierung an (hier von mir kommentiert):

ldi wr0, 0x0
out ddra, wr0 ; PORTA als Eingang!
out ddrb, wr0 ; PORTB als Eingang!
out ddrc, wr0 ; PORTC als Eingang!
ldi sekunde, 0


PORTA-C sind alle als Eingänge deklariert!

Gruß

Fred