Abend zusammen,
ich bin dabei eine Uhr zu basteln, Leider funktioniert sie noch nicht.
Ich habe erstmal mit dem Sekudnenteil angefangen. Alles andere ist noch
nicht drin.
Ich verwende zwei 7 Segmentanzeigen mit gemeinsamer Andoe.
Sie bekommen immer alle beide die Daten, egal ob nun die Zehner oder
Einerstelle beschrieben wird. Jedoch ist nur diejenige eingeschaltet,
die gerade dran ist.
Am MC gebe ich die Daten im Binärcode aus, die Anzeigen werden über
einen IC angesteuert.
Das mit dem Multiplexen funktioniert auch problemlos, jedoch der
Zählvorgang nicht.
Ich möchte, nachdem die Einerstelle von 0 bis 9 durchgezählt hat, wieder
eine 0 stehen haben und dann die Zehnerstelle aufwährtszählen lassen.
Jedoch ist genau dort das Problem, die Einerstelle wird bei der Zahl 9
nicht auf 9 gesetzt, sondern die Segmentanzeige zeigt irgendwelche
Buchstaben an, ich denke also es zählt einfach weiter.
Es scheint, als würde das Register r21 nicht auf 0 zurückgeschrieben,
wenn es den Wert 9 annimmt.
In der Simulation funktioniert es problemlos, in der Praxis aber nicht.
Wo steckt der Fehler ?
.include "m8def.inc"
.def temp = r16
.org 0x0000
rjmp main ; Reset Handler
.org OVF0addr
rjmp timer0_overflow ; Timer Overflow Handler
main:
ldi temp, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
sbi DDRD, 2
sbi DDRD, 3
sbi DDRB, 0
sbi DDRB, 1
sbi DDRB, 2
sbi DDRB, 3
ldi r21, 0b00000000
ldi r29,9
ldi temp, 0b00000011 ; CS00 setzen: Teiler 1
out TCCR0, temp
ldi r20,0b11100001
ldi temp, 0b00000001 ; TOIE0: Interrupt bei Timer
out TIMSK, temp
sei
loop:
out PORTB, r23 //schribe die Daten an beide Anzeigen
ldi r24, 0b00000100 ; gebe Anzeige 1 frei, nur sie wird leuchten
out PORTD, r24
ldi r24, 0b00000000; Anzeige 1 ausschalten
out PORTD,r24
out PORTB, r21 //schribe die Daten an beide Anzeigen
ldi r24, 0b00001000 ; gebe Anzeige 2 frei, nur sie wird leuchten
out PORTD, r24
ldi r24, 0b00000000; Anzeige 2 ausschalten
out PORTD,r24
rjmp loop
timer0_overflow: ; Timer 0 Overflow Handler
go:
dec r20
brne end
//was jetzt kommt passier jede Sekunde genau einmal
esek: //Diese Schleife ist für die Eienrstelle der Sekunden
verantwortlich
inc r21 //Vergroessere die Sekunden
mov r30, r29 //sichere r29. In r 29 steht die Zahl 9.
sub r29, r21 //Es wird festgestellt, wann die Einerstelle einmal
durchgelaufen ist, um dann wieder von 0 anfangen zaehlen zu koennen und
um die Zehnerstelle zu vergroessern
breq zsek
rjmp q
zsek:
mov r29, r30 //stelle r29 wieder her, denn durch die Subtraktion oben
ist es überschrieben worden
ldi r21,0b00000000 //stelle die eineranzeige wieder auf 0
inc r23 // vergroeßere die Zehnerstelle
endzsek:
// schreibe oben was jede sek passieren soll
q:
ldi r20,0b11100001
end:
reti
Ich kenns jetzt nur vom 8051 her, aber warum nimmst du den sub-Befehl und keinen cp-Vergleich mit einer Konstanten? Du scheinst ja abzuziehen und zu springen, wenn das Ergebnis kleiner 0 wird (9-10=255 und Überlauf). Die Zehnerstelle kann dir so aber generell auch noch überlaufen, oder?
Ich verstehe nicht warum das im Simulator funktioniert aber nicht in der Schaltung selber. r21 hat nach einer Runde der Einerstellen im Simulator den Wert 0, aber bei mir auf der Anzeige nicht. Naja ich habe jetzt nicht den Befehl sub verwendet, sondern einfach eine Zählschleife genommen, die 10 mal runterzählt. Damit klappt es.
Im Prinzip könnte man das so machen:
1 | ... |
2 | inc r21 ;erhöhe Sekunden-Einer |
3 | cpi r21,10 ;ersten ungültigen Wert (10) erreicht? |
4 | brne weiter ;nein, weiter... |
5 | |
6 | clr r21 ;ja, auf 0 setzen |
7 | inc r23 ;Sekunden-Zehner hochzählen |
8 | cpi r23,6 ;ersten ungültigen Wert (6) erreicht? |
9 | brne weiter ;nein, weiter... |
10 | |
11 | clr r23 ;ja, bei 0 beginnen |
12 | inc min_e ;Minuten-Einer hoch |
13 | cpi min_e,10 ;Überlauf? |
14 | brne weiter ;nein, weiter... |
15 | |
16 | clr min_e ;ja, auf 0 |
17 | inc min_z ;Minuten-Zehner hoch |
18 | cpi min_z,6 ;Überlauf? |
19 | brne weiter ;nein, weiter... |
20 | |
21 | inc Stu_e ;Stunden-Einer, Stunden-Zehner, Tage-Einer... |
22 | ;... Tage-Zehner, Monate-Einer, Monate-Zehner, Jahre-Einer, usw... |
23 | weiter: |
Auf weitere Dinge wie SREG-Sicherung oder Auslagerung der Uhr-Variablen ins SRAM möchte ich jetzt noch nicht hinweisen, aber Du solltest langam versuchen, den Programmtext halbwegs lesbar zu formatieren. ...
Den Befehl cpi kannte ich noch garnicht. Damit geht es besser, danke
jochen wrote: > Den Befehl cpi kannte ich noch garnicht. Damit geht es besser, danke Das Datenblatt Deines AVRs enthält ziemlich weit hinten zwei Tabellen. Eine listet alle verfügbaren Befehle auf, die zweite alle verfügbaren I/O-Register und ihre Bits. Drucke Dir doch mal beide Tabellen als eine Art Arbeitsblatt aus. Die Befehlsübersicht enthält neben den Namen auch noch die sehr hilfreichen Angaben: Operanden, Kurzbeschreibung, Operation (als Formel), Flagbeeinflussung und Anzahl der Takte. Sie sind auch schön nach Funktion sortiert, man übersieht also einen "alternativen" Befehl nicht so schnell. Gerade als Anfänger vergisst man schnell mal die entsprechenden Bezeichnungen, so dass eine Liste mit den Bezeichnungen schon sehr hilfreich sein kann (Schreibweise). ...
Ja dann werde ich mir das mal ausdrucken. Die Uhr funktioniert jetzt soweit, danke dass ihr mir bis hierhin geholfen habt. Ich habe jedoch in einem anderen Beitrag noch etwas zur Helligkeit geschrieben, wäre super wenn wir das noch klären könnten.
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.