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.