Forum: Mikrocontroller und Digitale Elektronik Stoppuhr mit Interrupt (8051)


von Jochen Huber (Gast)


Lesenswert?

Hallo ihr!

Ich brauche ganz dringend eure Hilfe. Ich bin noch Anfänger im
Programmieren mit dem 8051 Mikrocontroller und habe hier mal einen
Versuch gestartet.
Ich habe ein Stoppuhrprogramm geschrieben welches auf einer BCD 7
Segment Anzeige ausgegeben wird.
Die BCD-7-Segment Anzeige ist an Port 1 und 2 angeschlossen, eine
Tasterplatine ist an Port 0 angeschlossen...
Der Mikrocontroller hat 12 Mhz.

Was nun mein Problem ist:
Ich benötige einen Befehl oder ein Programmteil welches das ganze
Stoppuhrprogramm startet und einen Befehl zum Stoppen. Außerdem möchte
ich einen Reset einbauen!
Das Programm sollte wenn möglich nicht allzu arg verändert werden, d.h.
das Programm soll weiterhin mit Interrupt laufen. Da dies eines der
wenigen Dinge ist die ich verstehe....

Nun das Programm:

$include (reg52.inc)

Minutentaster  bit P0.0
Stundentaster  bit P0.1
Starttaster    bit P0.2
Resettaster    bit P0.3


org 0000h
  LJMP start




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



org 0100h
startabfrage:  JB Starttaster,start        ;Stoppuhrprogramm starten 
wenn
Taster gedrückt
          LJMP startabfrage
start:  CALL initRegister
      CALL initTimer0
loop:    JB Resettaster,springer
springer:LJMP initRegister

      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



Danke für schnelle Antworten!

von Stephan H. (stephan-)


Lesenswert?

wie ich die Sache sehe, sollte der Starttaster nichts anderes tun als
SETB TR0 beim 1. Betätigen und CLR TR0 beim 2. Betätigen.

Damit läuft der Timer erst beim drücken los. Wie ne echte Uhr.
Und stoppt beim 2. Drücken, wie ne......

Beim Init muß dann aber SETB TR0 raus !!!

OK so oder falsch verstanden ??

von Jochen Huber (Gast)


Lesenswert?

Also die Idee ist glaube ich gut, aber wie setze ich das ganze um????

Also vor allem die einbindung der Abfrage der Taster wäre interessant!

von Stanislaus Kroschnialoschnitz (Gast)


Lesenswert?

wie wärs wenn du in dein Hauptprogramm folgendes einbaust:

org 0100h
endlos:      JNB Starttaster,n1
               CALL initRegister
               CALL neueUhrzeit
               CLR merkerStop
               JB Starttaster,endlos
               LJMP endlos

n1:        CALL initRegister
               CALL initTimer0
          JNB stopTaster,endlos
               SETB merkerStop


Oder funktioniert das nicht? Kann mich da jemand berichtigen?

von Stephan H. (stephan-)


Lesenswert?

Taster zB an P1.0

Setb p1.0 oder mov P1,#ff oä. um den Port als Eingang zu haben
dann entweder pollen oder flankentriggern
zB. Pollen
abfrage:    mov a,p1
            jb  a.0,abfrage

            jetzt weiter da taste gedrückt
            Hilfsflag schon 1 ?? Ja > dann SetB Tr0; Hilfsflag nullen
            nein > setb  Taster  ( Hilfsflag )
       zB.: warten für 20ms oä. wegen prellen
            und nochmal Taster abfragen ob gedrückt
            jmp abfrage

oder Du nimmst Flankengetriggerten Interrupt EXT0 EXT1
 gleiches Prinzip

ABER..... Du mußt die Taster entprellen !!!!
Soft oder Hardwareseitig. Keine Ahnung wie genau die Uhr sein soll.
Im Einfachsten Fall ein FF am Taster.

von Stephan H. (stephan-)


Lesenswert?

@Jochen
es vergeht einiges an Zeit bis alles initialisiert ist und der Timer
läuft. !!!Die fehlt nachher !!!!

von Jochen Huber (Gast)


Lesenswert?

Ich glaube ich stehe vor immer mehr Probleme...

Gäbe es eine Möglichkeit das nicht allzuviel Zeit vergeht beim
initialisieren?
Und wo müsse ich dann diese Abfrage von oben einbauen?

von Stephan H. (stephan-)


Lesenswert?

mach den Init als erstes fertig komplett mit timerwerten
und starte den Timer erst (Setb Tr0) erst bei Tastenerkennung !!!

von Hannes L. (hannes)


Lesenswert?

Ich bin mal frech:
http://www.hanneslux.de/avr/stopuhr/index.html

Aber vielleicht hilft es ja...

...

von neutron (Gast)


Lesenswert?

Ich möchte mit C eine machen.
Kann mir jemand helfen?

im vorraus Danke;)

von Markus_8051 (Gast)


Lesenswert?

Geh Dein Programm nochmal schritt für schritt logisch durch und
korrigiere es, bevor Du es hier dann noch einmal postest:

z.B.:
loop:    JB Resettaster,springer
springer:LJMP initRegister

macht keinen Sinn! : Wenn Resettaster dann verzweige nach springer,
wenn nicht, dann macht er auch bei springer weiter.

Außerdem solltest Du Deine Unterprogramme noch einmal untersuchen: Wenn
Du mit CALL in ein UPRO verzweigst, mußt Du mit RET wieder raus. Wenn Du
mit JMP reinspringst, darfst Du NICHT mit RET wieder raus.

Vor dem ersten CALL mußt Du unbedingt den Stack initialisieren - oder
Dir zumindest Gedanken machen, auf welchem Wert er gerade steht und in
welche Richtung er sich bewegt.

Gruß,
Markus_8051

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.