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
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
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.
ach ich glaub ich muss nur etwas drüber nachdenken, dann verstehe ich das schon :P
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..
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...
magst mir noch kurz erklären, wieso A6h dazuaddieren? 166? :) dank dir.. sirpreis
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
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.
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
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.
"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
@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
"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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.