Forum: Mikrocontroller und Digitale Elektronik Fehler in Zählvorgang meiner Uhr


von jochen (Gast)


Lesenswert?

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

von Thomas (Gast)


Lesenswert?

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?

von jochen (Gast)


Lesenswert?

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.

von Hannes L. (hannes)


Lesenswert?

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.

...

von jochen (Gast)


Lesenswert?

Den Befehl cpi kannte ich noch garnicht. Damit geht es besser, danke

von Hannes L. (hannes)


Lesenswert?

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).

...

von jochen (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.