mikrocontroller.net

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


Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Prinzip könnte man das so machen:
...
 inc r21                   ;erhöhe Sekunden-Einer
 cpi r21,10                ;ersten ungültigen Wert (10) erreicht?
 brne weiter               ;nein, weiter...

 clr r21                   ;ja, auf 0 setzen
 inc r23                   ;Sekunden-Zehner hochzählen
 cpi r23,6                 ;ersten ungültigen Wert (6) erreicht?
 brne weiter               ;nein, weiter...

 clr r23                   ;ja, bei 0 beginnen
 inc min_e                 ;Minuten-Einer hoch
 cpi min_e,10              ;Überlauf?
 brne weiter               ;nein, weiter...

 clr min_e                 ;ja, auf 0
 inc min_z                 ;Minuten-Zehner hoch
 cpi min_z,6               ;Überlauf?
 brne weiter               ;nein, weiter...

 inc Stu_e                 ;Stunden-Einer, Stunden-Zehner, Tage-Einer...
 ;... Tage-Zehner, Monate-Einer, Monate-Zehner, Jahre-Einer, usw...
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.

...

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Befehl cpi kannte ich noch garnicht. Damit geht es besser, danke

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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).

...

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.