Forum: Mikrocontroller und Digitale Elektronik Assembler-Programm für Binäruhr


von sirpreis (Gast)


Lesenswert?

Servus,

ich will mit n paar Kollegen ne Binäruhr bauen, (zum an die Wand
hängen), ähnlich wie diese hier:
www.thinkgeek.com/cubegoodies/lights/59e0/

Jetzt hab ich aber gar keine ahnung von Assembler, habe da mal bissel
was zusammenkopiert und selbst was versucht, aber das klappt irgendwie
nicht, wie ich will :P kann mir da mal jemand n bissel hilfestellung
geben?


INCLUDE 89C2051.mc

LJMP Initialisierung 'Überspringe Interruptroutine nach einem Reset
(000Bh): 'Einsprungadresse Interrupt Timer 0

'Realisierung der 50mS Zeitbasis:
MOV A,TL0 'Speicher TL0 im Akku (Zeit seit Überlauf)
ADD A,#B3h 'A = A + (Grundeinstellung B0 + 3)
MOV TL0,A 'Setze den errechneten Wert wieder in den TL0

'Routine zum "Hochzählen" der Uhrzeit:
INC R7 'Register 7 speichert die Zahl der Interrupts

CJNE R7,#20,Zurück 'Wenn bereits 20 Interrupts, dann:
MOV R7,#00 'Interruptzähler auf 0
INC R0 'Sekunden = Sekunden + 1


'Der Teil ist von mir, nicht drüber lachen :P

CJNE R0,#1,Zurück 'Überprüft ob Sekunden = 1
SETB P1.0
SETB P1.1
SETB P1.2
SETB P1.3 'Alle LEDs wieder aus (schwachsinn?!?)
CPL P1.0 '1 Sekunde >= erste LED an

CJNE R0,#2,Zurück
SETB P1.0
SETB P1.1
SETB P1.2
SETB P1.3 'Alle LEDs wieder aus (schwachsinn?!?)
CPL P1.1 '2 Sekunden >= zweite LED an


CJNE R0,#3,Zurück
SETB P1.0
SETB P1.1
SETB P1.2
SETB P1.3 'Alle LEDs wieder aus (schwachsinn?!?)
CPL P1.0
CPL P1.1 '3 Sekunden >= erste + zweite LED an


'Ja und so weiter, aber das muss ja viiiiiiiiiiiel einfacher gehen,
aber da ich keine ahnung habe...




CJNE R0,#60,Zurück 'Wenn Sekunden = 60, dann
MOV R0,#0 'Sekunden = 0
INC R1 'Minuten = Minuten + 1

CJNE R1,#60,Zurück'Wenn Minuten = 60, dann
MOV R1,#0 'Minuten = 0
INC R2 'Stunden = Stunden + 1

CJNE R2,#24,Zurück 'Wenn Stunden = 24, dann
MOV R2,#0 'Stunden = 0

Zurück:
RETI 'Zurück aus der Interruptbehandlung ins Programm

'************************************************

INITIALISIERUNG:
MOV R0,#0 'Sekunden auf 0
MOV R1,#0 'Minuten auf 0
MOV R2,#0 'Stunden auf 0
MOV R7,#0 'Interruptzähler auf 0

'Grundeinstellung des Timer 0 und der dazugehörigen Interrupts:
MOV TMOD,#01h 'Timer 0 Modus = 1
MOV TH0,#3Ch 'High Byte vom Timer 0 setzen
MOV TL0,#B0h 'Low Byte vom Timer 0 setzen
SETB EA 'Interruptbehandlung aktivieren
SETB ET0 'Interrupt für Timer 0 aktivieren
SETB TR0 'Timer 0 Start

Start:
LJMP Start



Vielleicht kurz zur Erklärung, die LEDs sind halt an den Ports am
Mikrocontroller angeschlossen (muss mich wohl auch nochmal
schlaumachen, wo und wie die drangepackt werden).. naja, die Uhr ist ja
selbsterklärend, und je nach Sekunden, Minuten, Stunden sollen dann die
jeweiligen LEDs angesprochen werden

Wäre jeder Hilfe dankbar..

sirpreis

von Thomas Schattat (Gast)


Lesenswert?

Hallo,
geht auch eingacher:
Anstelle immer die Bytes mit einem Wert zu vergleichen und ggf zu
springen kann man folgendes tun, Beispiel fuer R0:

MOV A, R0
ADD A, #01h
DAA
MOV R0, A

Damit ist ein BCD Zaehler realisiert. DAA bedeutet "Decimal Adjust
Accu", wenn beim Addieren ein Nibble groesser als 9 vorkommt wird es
richtiggestellt.
Beispiel:

A ist 19h (0001 1001 b)
eins dazu:
A ist nun 1Ah (0001 1010 b)
nun DAA:
A ist nun 20h (0010 0000 b), das ist was gewuenscht war.

Machste mit allen Zaehlregistern und gibst das so auf die Ports aus,
dann kommt genau das Ergebnis das gewuenscht wurde heraus.

EASY??

Gruss
Thomas

von sirpreis (Gast)


Lesenswert?

also die möglichkeit für
CJNE R0,#60,Zurück 'Wenn Sekunden = 60, dann
etc. eintauschen? und was genau bringts mir?
wenn R0 00011001 ist, also 25 sekunden,
was bringt mir dann dieser bcd zähler?
kommt doch später
00100000, 32_10 raus... :)

aber danke schonmal.

von sirpreis (Gast)


Lesenswert?

ach ich glaub ich muss nur etwas drüber nachdenken, dann verstehe ich
das schon :P

von sirpreis (Gast)


Lesenswert?

ich habs so mehr oder weniger verstanden,

nun, dann kann ich
ja das ganze immer auf den Port
geben,
MOV P1, A... dann stimmen die Einer
der Sekunden ja schonmal..
wie kann ich das jetzt machen, dass,
wenn das Highnibble (z.b. bei den Sekunden)
0101 (5) überschreitet (5, da ja nach 59
Sekunden wieder 0 kommt)
automatisch z.b. dem Lownibble in R1 eins
zuaddiert? :/
Ebenso dann bei den Stunden..

von Thomas Schattat (Gast)


Lesenswert?

Hallo,
Beispiel:
R3 hat die Sekunden BCD mässig
;Sekunden wie beschrieben hochzählen, dann:

MOV A, R3   ;Sekunden in Akku laden
ADD A, #A6h  ;A6h dazuaddieren
JNC weiter   ;Wenn es kein Carry gab war es noch nicht 60 oder größer
MOV R3, #0   ;Wenn doch Sekunden auf Null und minuten genau so
weiterzählen.

Minuten weiterzählen wie die Sekunden...

weiter:   ; hier geht es bei weniger  als 59 (59h+Ahh = FFh)
; Ausgabe sollte folgen...

von sirpreis (Gast)


Lesenswert?

magst mir noch kurz erklären, wieso A6h dazuaddieren?
166? :)

dank dir..
sirpreis

von sirpreis (Gast)


Lesenswert?

ach ja, wie kann ich n byte "invertieren"? XOR R0,#255 ?

von Peter D. (peda)


Lesenswert?

CJNE R0,#60,Zurück 'Wenn Sekunden = 60, dann
MOV R0,#0 'Sekunden = 0
INC R1 'Minuten = Minuten + 1

CJNE R1,#60,Zurück'Wenn Minuten = 60, dann
MOV R1,#0 'Minuten = 0
INC R2 'Stunden = Stunden + 1

CJNE R2,#24,Zurück 'Wenn Stunden = 24, dann
MOV R2,#0 'Stunden = 0



Das ist doch vollkommen o.k., wo ist jetzt das Problem ?

Die Zehner und Einer kriegst Du ja bequem mit "DIV AB" raus.

Und dann ab auf die LEDs (7-Segment dekodieren willst Du ja nicht).


Aber ein 2051 hat nur 15 Pins, das reicht nicht für 20 LEDs, es sein
denn, Du multiplext.



Peter

von sirpreis (Gast)


Lesenswert?

wenn du mir kurz erklärst, wie ich DIV AB nutze? wo stehen dann die
Zehner und die Einer? dann müsste ich sie ja nur noch "invertieren"
(oder wie das auch immer heißen mag, und auf den port geben.

von sirpreis (Gast)


Lesenswert?

ach ja..

INCLUDE 89C51.mc

:)

von Thomas Schattat (Gast)


Lesenswert?

59h + A6h ist genau FFh, also gerade noch kein Carry. Ab 60h gibt es ein
Carry und der Sprungbefehl feuert, alles klar?
ich wuerde folgendermasse programmieren:

;Sekunden R0
;Minuten  R1
;Stunden  R2

INC R7 'Register 7 speichert die Zahl der Interrupts

CJNE R7,#20,Zurück 'Wenn bereits 20 Interrupts, dann:
MOV R7,#00 'Interruptzähler auf 0

;ab hier von mir:

MOV A, R0
ADD A, #01h
DA A
MOV R0, A   ;bis hier ist R0 eins weiter
ADD A, #A6h
JNC weiter  ;wenn Carry dann wars 60, sonst weiter
MOV R0, #0  ;Sekunden auf 0
MOV A, R1   ;dasselbe mit den Minuten...
ADD A, #01h
DA A
MOV R1, A
ADD A, #A6h
JNC weiter  ;wenn Carry dann wars 60, sonst weiter
MOV R1, #0  ;und den Stunden...
MOV A, R2
ADD A, #01h
DA A
MOV R2, A
ADD A, #DCh ;denn: 24h+DCh=100h, also Carry bei >23
JNC weiter
MOV R2, #0  ;war 24, also auf 0
weiter:
;ab hier Multiplexausgabe der Zeiten an LEDs

von crazy horse (Gast)


Lesenswert?

und noch was ganz anderes: den Zeitzähler als reinen Binärzähler, der
jede Sekunde incrementiert wird, Zähler geht bis 60(s)*60(min)*24(h),
wird also bei 86400 wieder auf 0 gesetzt. Der eigentliche Zähler wird
damit einfacher, dafür musst du dann bei der Ausgabe etwas mehr
rechnen, mehrere Divisionen. Gibt fertige Routinen, die sowohl den
Ganzteil- als auch den Rest der Division liefern.

Zähler/60: Rest=Sekunden
Ergebnis/60: Rest=Minuten
Ergebnis: Stunden

Dann nochmal s,min und Stunden in Einer und 10er teilen, ausgeben,
fertig. Sieht erstmal komplizierter aus, als es ist.
Das ist keine Wertung, was besser ist, viele Wege führen nach Rom. Mir
persönlich gefällt diese Lösung besser.

von Peter D. (peda)


Lesenswert?

"wenn du mir kurz erklärst, wie ich DIV AB nutze?"

Z.B.:

59 / 10 = 5 Rest 9

Wenn man Assembler programmiert, sollte man sich doch mal den
Befehlssatz ansehen.


Peter

von sirpreis (Gast)


Lesenswert?

@crazy horse
hört sich ganz nett an, gefällt mir besser als die andere lösung.
naja, hab leider noch nie was wirklich mit assebler programmiert (und
auch sonst recht wenig)... wie siehtn das mit solch einem "großen"
binärzähler aus.. wie kann ich denn bis 86400 zählen? son byte geht
doch nur bis 255 oder wie? :)

@peter dannegger
haste nen link zum Befehlssatz? deine rechnung war mir schon klar, nur
die praktische anwendung von DIV AB nicht :)

danke, sirpreis

von Peter D. (peda)


Lesenswert?

"haste nen link zum Befehlssatz?"

Z.B:

http://www.atmel.com/dyn/resources/prod_documents/doc0509.pdf


Peter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.