Forum: Mikrocontroller und Digitale Elektronik Stoppuhr Zusatzfunktionen


von Manfred Meier (Gast)


Lesenswert?

Hallo!

Zuerst einmal muss ich sagen was ich habe:
Ich habe ein Mikrocontroller System mit einen 12Mhz Mikrocntroller.
Die Ausgabe der Stoppuhr erfolgt auf der BCD-7-Segment Anzeige (welche
an Port 1 und 2 des Mikrocontrollers angeschlossen ist). Außerdem ist
eine Schalterplatine an Port 0 angeschlossen für Zusatzfunktionen.

Ich habe mittlerweile mit meinen Basis Kenntnissen folgendes Programm
programmiert:


---------------------------------------------------

$include (reg52.inc)

Minutentaster  bit P0.0
Stundentaster  bit P0.1
org 0000h

      LJMP start


;Einsprungadresse Interrupt-Serviceroutine für Timer 0
org 000Bh
      LJMP isrTimer0


org 0100h
start:  CALL initRegister
      CALL initTimer0
loop:    LJMP loop      ;Endlosschleife

initRegister:
      MOV  R0,#0      ;bestimmt welche der Anzeigen aktiv ist
      MOV  R1,#0       ;Zähler von o bis 249 -->4ms*250 = 1 Sec

      MOV  R2,#0      ;Sekunden Einer
      MOV  R3,#0       ;Sekunden Zehner
      MOV  R4,#0       ;für Segment rechts          Minuten Einer
      MOV  R5,#0       ;für Segment Mitte rechts      Minuten Zehner
      MOV  R6,#0       ;für Segment Mitte links      Stunden Einer
      MOV  R7,#0       ;für Segment links          Stunden Zehner

      RET

initTimer0:

      SETB  ET0          ;Freigabe Timer0. Bit im Reg IE, Reg.-Adresse 
A8h

      SETB   EA            ;Globale INT Freigabe. Bit im Reg IE

      MOV  TMOD,#00000001b  ;Timer0 konfiguieren, Modus1: 16bit Zaehler

      MOV  TL0,#060h      ;Timer0 vorladen

      MOV  TH0,#0F0h      ;65536 - 4000 = 61536 = F060h (4ms)

      SETB  TR0          ;Start Timer0

      RET

;Interrupt-Service-Routine für Timer0
isrTimer0:


      MOV  TL0,#060h      ;Timer0 erneut vorladen

      MOV  TH0,#0F0h      ;65536 - 4000 = 61536 = F060h (4ms)

      CALL  neueUhrzeit      ;neue Uhrzeit berechnen

      CALL  ausgabe        ;Ausgabe auf Anzeige

      RETI              ;Ende der Interrupt-Service-Routine



neueUhrzeit:

         INC R1        ; erhoehe Register 1
         CJNE R1,#250d,weiter      ;Springe nach weiter wenn der Inhalt
von R1 ungleich 250d ist
         MOV  R1,#0d            ;Lade Register 1 mit dem Wert 0

         JB Minutentaster,mSek    ;Springe nach mSek wenn Sektaster 1
ist
         JB Stundentaster,mMin    ;Springe nach mMin wenn Mintaster 1
ist
         INC R2              ; erhoehe Register 2
         CJNE R2,#10d,weiter      ;Springe nach weiter wenn der Inhalt 
von
R2 ungleich 10d ist
         MOV R2,#0d            ;Lade Register 2 mit dem Wert 0
         INC R3              ; erhoehe Register 3
         CJNE R3,#10d,weiter      ;Springe nach weiter wenn der Inhalt 
von
R3 ungleich 10d ist
         MOV R3,#0d            ;Lade Register 3 mit dem Wert 0
mSek:    INC R4              ; erhoehe Register 4
         CJNE R4,#10d,weiter      ;Springe nach weiter wenn der Inhalt 
von
R4 ungleich 10d ist
         MOV R4,#0d            ;Lade Register 4 mit dem Wert 0
         INC R5              ; erhoehe Register 5
         CJNE R5,#06d,weiter      ;Springe nach weiter wenn der Inhalt 
von
R5 ungleich 10d ist
         MOV R5,#0d            ;Lade Register 5 mit dem Wert 0
mMin:    INC R6              ; erhoehe Register 6
         CJNE R6,#6d,m2          ;Springe nach m2 wenn der Inhalt von R6
ungleich 6d ist
         CJNE R7,#10d,m2        ;Springe nach m2 wenn der Inhalt von R7
ungleich 0d ist
         MOV R6,#0            ;Lade Register 6 mit dem Wert 0
         MOV R7,#0            ;Lade Register 7 mit dem Wert 0



m2:      CJNE R6,#10,weiter      ;Springe nach weiter wenn der Inhalt 
von
R6 ungleich 10 ist
      MOV R6,#9            ;Lade Register 6 mit dem Wert 9
      INC R7              ; erhoehe Register 7
      LJMP weiter            ;aufrufen von weiter

weiter:  RET                ;Rücksprung aus dem Unterprogramm


ausgabe:  INC   R0
      CJNE  R0,#04,rechts
      MOV  R0,#0

rechts:  CJNE  R0,#0,mire
      MOV  A,R4
      CALL  BCD7Seg
      MOV  P1,A
      MOV  P2,#00001110b
mire:    CJNE  R0,#1,mili
      MOV  A,R5
      CALL  BCD7Seg
      MOV  P1,A
      MOV  P2,#00001101b
mili:    CJNE  R0,#2,links
      MOV  A,R6
      CALL  BCD7Seg
      MOV  P1,A
      MOV  P2,#00001011b
links:  CJNE  R0,#3,m1
      MOV  A,R7
      CALL  BCD7Seg
      MOV  P1,A
      MOV  P2,#00000111b
m1:    RET




;; Wandelt vom BCD-Code in den 7-Segment-Code
BCD7Seg:  INC  A
      MOVC  A,@A+PC
      RET
      DB  3Fh, 06h, 5Bh, 4Fh, 66h, 6Dh, 7Dh, 07h, 7Fh, 6Fh




END

---------------------------------------------------------

Das Programm funktioniert soweit auch einwandfrei....
Ich möchte jetzt nur die Anzeige etwas umwandeln. Die Anzeige soll um
ein Segment nach Rechts gerückt werden, das würde bedeuten:
Segment Rechts: Hundertstel Zehner
Segment Mitte Rechts: Sekunden Einer
Segment Mitte Links: Sekunden Zehner
Segment Links: Minuten

Ich weiß nicht ob ich irgendwie gerade voll auf dem Schlauch stehe oder
was los ist, aber egal was ich tue es funktioniert nicht!

Achso und was ich noch Programmieren möchte ist ein Reset, vielleicht
hat jemand von euch hierfür auch einen Vorschlag?

Ich bin wirklich Anfänger mit Assembler und fände es gut wenn das
Programm weiterhin so verständlich bleibt wie mein jetziges.

Vielen Dank schoneinmal im Voraus für die schnelle Antwort!

von Rahul (Gast)


Lesenswert?

Würdest du die Uhr im RAM realsieren (also nicht mit den Registern),
könnte man durch ändern des Anzeige-Daten-Einstiegspointers die Anzeige
einfach um eine Stelle (oder sogar noch mehrere) verschieben.

Für das Reset musst du eigentlich nur eine weitere Tastenabfrage
einbringen, die zu einer Stelle verzweigt, wo alle Register auf 0
gesetzt werden.

von Manfred Meier (Gast)


Lesenswert?

Und wie funktioniert das mit dem realisieren im RAM?

Ich bin noch sehr Neu auf diesem Gebiet und habe mir mein Programm
grade so zusammenbasteln können.

Gibt es einen Befehl die ich alle Register auf einmal auf 0 setzen
kann?

von Rahul (Gast)


Lesenswert?

>Und wie funktioniert das mit dem realisieren im RAM?

Weiß ich leider auch nicht. Da ich einerseits in C, andererseits
überwiegend AVR programmieren.

>Gibt es einen Befehl die ich alle Register auf einmal auf 0 setzen
kann?

Vermutlich nicht. Da wirst du einfach alle verwendeten Register der
Reihe nach "clearen" müssen.

Falls du Interesse am Lesen von Büchern hast: "Das Mikrocontroller
Kochbuch" von Andreas Roth ist sowas wie die Bibel für
8051er-Controller.

von Karl H. (kbuchegg)


Lesenswert?

Gleich vorweg: Ich verstehe nichts vom 8051 Assembler an sich.

Aber:

         MOV R3,#0d            ;Lade Register 3 mit dem Wert 0
mSek:    INC R4              ; erhoehe Register 4

Kommentare wie diese kannst du dir sparen. Da steht im Kommentar
genau dasselbe wie im eigentlichen Quelltext. Super, da wird
'Lade Register 3 mit dem Wert 0'. Das sehe ich auch (oder kann
es erraten) wenn ich

         MOV R3, #0d

lese.
Die viel spannendere Frage ist doch: Was enthaelt den Register 3?
Sind da Zwetschken, Anzahl an Äpfel, Minuten, Stunden, Monate
oder was auch immer gespeichert?
Diese Information brauch ich, um zu verstehen was da vor sich
gehen soll.

Selbiges hier (und im Rest vom Code)

       INC R4              ; erhoehe Register 4

Als echter Österreicher sag ich da: "No, na. Erniedrigen wird er
wenn da schon INC steht". Warum wird da R4 erhöht? Was enthält denn
R4 überhaupt? Das sind die Fragen die mich da bewegen.

von Manfred Meier (Gast)


Lesenswert?

Also so genau kann ich das jetzt auch nicht kommentieren, ich habe das
Programm zusammen mit einem Freund geschrieben und ich bin eigentlich
der der definitiv sehr wenig ahnung von dem ganzen hat...

Aber vielleicht kann mir jemand ohne ausführliche Kommentare
weiterhelfen?

von Christian Rötzer (Gast)


Lesenswert?

Das stinkt doch wieder einmal zum Himmel:

Erst:
"Ich habe mittlerweile mit meinen Basis Kenntnissen folgendes Programm
programmiert"

Dann:
"ich habe das Programm zusammen mit einem Freund geschrieben"

Genau wie ich! Ich schreibe meine Programme auch immer zusammen mit
meinen Freunden. Ich nehme an Dein "Freund" hat kein Internet.

von Karl H. (kbuchegg)


Lesenswert?

> Achso und was ich noch Programmieren möchte ist ein Reset,
> vielleicht hat jemand von euch hierfür auch einen Vorschlag?

Fang mal damit an, das dürfte das Einfachere sein.

Was brauchst Du?
1. Du brauchst einen Tastet oder Schalter. Den irgendwie musst
   du den Reset ja ausloesen.

2. Du musst die Zahlenwerte für Minuten, Sekunden, etc auf
   0 setzen

Zu Punkt 1: Da ich Deine Hardware nicht kenne, kann ich auch
nicht sagen ob du einen Taster oder Schalter frei hast. Im
Zweifel wirst du halt einen nachrüsten müssen.
Da das bisherige Programm bereits Taster einliest, kannst du
dich daran orientieren wie das geht und mal den neuen Taster
auswerten.

Zu Punkt 2: Alle Zahlenwerte auf 0 setzen. Das sollte nicht so
schwer sein. Zumal Dein bisheriges Programm ja schon sowas
enthält. Ich zitieren

      MOV  R2,#0      ;Sekunden Einer
      MOV  R3,#0       ;Sekunden Zehner
      MOV  R4,#0       ;für Segment rechts          Minuten Einer
      MOV  R5,#0       ;für Segment Mitte rechts      Minuten Zehner
      MOV  R6,#0       ;für Segment Mitte links      Stunden Einer
      MOV  R7,#0       ;für Segment links          Stunden Zehner

das sieht doch schon genau so aus, wie das wonach du suchst.

von Manfred Meier (Gast)


Lesenswert?

@ Christian Rötzer

Ich weiß nicht was du von mir denkst aber mein Freund hat wirklich kein
Internet. Und dadurch das wir uns NOCH in den Semesterferien befinden
sehe ich ihn auch nicht (da er in Urlaub ist) und ich möchte eben
weiter Programmieren.


Zur Info ich habe eine Schalterplatine und eine Tasterplatine zur
Verfügung. Ich werde wahrscheinlich eher die Tasterplatine verwenden
(ist günstiger für Start, Stopp, Reset, usw.).


Danke für die bisherigen Antworten!
Wenn jetzt noch jemand eine Möglichkeit hätte die ganze Stoppuhr in
diesem normal verständlichen Code eine Anzeige nach rechts zu
verschieben, wie es in meinen ersten Beitrag schon erwähnt wurde. Dann
wäre ich glücklich!

von Rahul (Gast)


Lesenswert?

Vielleicht ne Schweine-Methode, funktioniert aber wunderbar:
Schreib dir eine zweite Ausgaberoutine, die im "Stopp-Uhr-Modus"
statt der "Standard-Uhrzeit-Anzeige" angesprungen wird.
Das wäre die schnellste Möglichkeit, zum Ziel zu kommen.

von Stephan H. (stephan-)


Lesenswert?

High Low Manfred,

nach dem was ich sehe wird die Anzeige mit P1 und P2 angesteuert.
An P1 liegen die Segmente und P2 macht die Stelle.
Schau dir die Null in P2 an von Stelle zu Stelle. Siehst Du wie sie
wandert ??? Genau damit kannst du die Anzeige verschieben.
Bei 00001110b geht die letzte Stelle an und bei 00000111b geht die
1.Stelle an.

00001110 Minuten Einer
00001101 Minuten Zehner
00001011 Stunden Einer
00000111 Stunden Zehner

Alle anderen sind immer High. ( oder 1 ).
An P2 sind doch die Transistoren für die Anzeigen ????

Also nimm den richtigen Wert für die Stelle in P1 und mit P2 gibst Du
an welche Anzeige aktiv sein soll.

So denn

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.