Forum: Mikrocontroller und Digitale Elektronik Zeitkonstanten für Timer0 µC: SAB 80C517A


von Amy18146 (Gast)


Lesenswert?

Hallo Zusammen,

ich soll mittels dem µC SAB80C517A ein Lauflicht im 1Sekunden-Takt in 
Assembler programmieren.

für Timer0 Mode1 müssen TH0 und TH1 Werte gesetzt werden. Jedoch weiß 
ich noch nicht genau, wie ich diese berechne.

für einen 10ms-Timer habe ich im Internet folgende Berechnung gefunden:
10ms= 10000µs
2^16= 65535
--> 65535 - 10000 = 55535 --> 0xD8EF

--> TH0 = 0xD8
--> TLO = 0xEF

Aber wie verhält es sich nun bei 1Sekunde? Wenn ich dieses 
Berechnungsschema analog für 1sekunde anwende, müsste ja folgendes 
rauskommen.
1s = 1000000µs

-->65535 - 1000000 --> hier erhalte ich dann aber einen negativen Wert! 
und das kann ich mir nicht vorstellen. Kann mir jemand helfen???

Vielen Dank im Vorraus!

von 8051 (Gast)


Lesenswert?

Amy18146 schrieb:
> -->65535 - 1000000 --> hier erhalte ich dann aber einen negativen Wert!
> und das kann ich mir nicht vorstellen. Kann mir jemand helfen???

Richtig, der Timer müsste mehr Zählen als reingeht. Du brauchst eine 
weitere Zählvariable. Bei jedem Timerüberlauf wird sie inkrementiert und 
vergrößert damit den Zählbereich.

von Amy18146 (Gast)


Lesenswert?

hm...ok, aber ich verstehe dann noch nicht genau, wie ich die weitere 
zählvariable dann mit TH0 und TL0 in verbindung bringe....

jemand hatte mir gesagt gehabt, dass  TH0 den Wert C0hex und TL0 den 
Wert 63hex hat. da verstehe ich die berechnung nicht, bzw. wie man auf 
die werte TH0 und TL0 kommt.

TH0 * 256 + TL0
99*256=25344 + 192 = 25536 = 63C0hex

weißt das einer vielleicht?

von Wilhelm F. (Gast)


Lesenswert?

Amy18146 schrieb:

> Aber wie verhält es sich nun bei 1Sekunde?

Die Annahme ist wohl, daß dein 80517 mit einem Quarz 12MHz betrieben 
wird, und nicht im Slow-Down-Mode, der noch mal durch 8 teilen würde.

Dann ergibt sich ein Maschinenzyklus von exakt 1µs.

TH0 und TL0 ergeben zusammen das 16-bit-Register des Timer 0.

Der Timer zählt nicht nur bis 65535, sondern mit Überlauf bis 65536. 
Diese Zahl muß man für die Berechnung der Zeiten verwenden. Also, für 
10ms beispielsweise:

T0 = 65536 - 10000

Leider kann der Timer alleine nur bis 65536µs zählen.

Möchte man 1 Sekunde, muß man sich was ausdenken, z.B. eine weitere 
Zählvariable. Jetzt kann man schauen, wie man glatte Werte bekommt. Z.B. 
sind 1000000µs = 50000µs mal 20.

Also: Timerwert 50ms berechnen: T0 = 65536 - 50000.

Jedes mal, wenn der Timer jetzt überläuft, eine Zählvariable um 1 hoch 
zählen, und zwar bis 20. So erhält man die Sekunde.

Der Assembler hat spezielle Anweisungen, um den berechneten 16-bit-Wert 
in zwei 8-bit-Werte zu splitten: High und Low. Das muß man der Anleitung 
des Assemblers entnehmen, wie es genau funktioniert. Evtl. gehts auch 
mit Shift-Befehlen und Ausmaskierung der benötigten bits. Es ist von 
Assembler zu Assembler unterschiedlich.

Natürlich programmiert man für den Timer einen Interrupt, denn der Timer 
soll ja endlos durch laufen, und immer wieder mit dem berechneten Wert 
nachgeladen werden. Das ist beim Timer 0 noch mal etwas trickreich. Es 
gibt 2 Möglichkeiten, ihn nachzuladen. Entweder on-the fly, oder man 
stoppt ihn, subtrahiert die Stopzeit vom berechneten Wert, und startet 
ihn wieder. In diesem Interrupt zählt man die Zählvariable bis 20 hoch, 
und stellt sie dann wieder auf 0.

Der 80517 hat sicher auch einen anderen Timer mit Auto-Reload. Das müßte 
ich aber nachschauen, Timer 2 könnte das sein.

Mit dem 80C517A arbeite ich gelegentlich auch noch. Er ist zwar uralt, 
aber für eine Menge Spielereien reicht er immer noch. Kürzlich spielte 
ich noch mit einem Lauflicht an der PWM, damit kann man die LEDs dann 
auch sanft ein- und ausschalten. Ist aber etwas mehr Programmieraufwand.

von Amy18146 (Gast)


Lesenswert?

ok, vielen dank für deine ausführliche antwort. nun habe ich es 
verstanden.
folglich müsste mein code auch funktionieren:
; --------------------------------------------------------------------
;
; Lauflicht im Sekundentakt mittels Timer 0 Mode 1
;
; --------------------------------------------------------------------


$INCLUDE (REG517A.inc)


; Konstanten definieren
MODE   EQU 01H      ; Timer 0 Mode 1
Low   EQU B0H      ; Timerwert für 50ms berechnen:
HIGH   EQU 3CH      ; --> 65536 -50000 = 15536
        ; TH0 + TL0 = 15536 = 3CB0hex
        ; --> Zusätzliche Zählvariabel "ZAEHL",
        ;     die bei jedem Timerüberlauf um 1
                                ; erhöht (bis 20)
ZAEHL   EQU 20      ; Zählvariable mit Startwert 20dez (20 *
                                ; 50 ms = 1 sekunde)

CSEG at 00h      ; legt Codesegment auf 00hex fest
LJMP INIT      ; Sprung zu Initialisierung
ORG 000Bh      ; Sprungmarke zur ISR für Timer0
LJMP START      ; Sprung zu Start


; Initialisierungen
INIT:   MOVE A,#00h    ; Akku löschen
  MOV P4, #00h    ; Port 4 mit 00hex setzen
  MOV TMOD, #MODE    ; Timer 0 Mode 1
  MOV TH0, #HIGH    ; schreibe in TH0 den Wert von HIGH
  MOV TL0, #LOW    ; schreibe in TL0 den Wert von LOW
  MOV R2, #ZAEHL    ; R2 ist Zählvariable
  MOV TF0, #00h    ; Überlaufflag des Timers auf Null setzen


; Hauptprogramm
START:  MOV TH0, #HIGH    ; schreibe in TH0 den Wert von HIGH
  MOV TL0, #LOW    ; schreibe in TL0 den Wert von LOW
  SETB EAL    ; allgem. Interruptsperre aufgehoben
  SETB ET0    ; externen Interrupt (Timer0) freigeben
  SETB TR0    ; Timer0 starten
  DJNZ R2,START    ; erhöhe R2 um "1" und springe zu START
                                ; wenn ungleich 0
  MOV R2, #ZAEHL    ; R2 ist Zählvariable = 20
  INC A;      ; Akku incrementieren
  MOV P4, A    ; Akkuinhaltausgabe auf Ports (LEDs)
  LJMP INIT    ; Sprung zu Start --> Lauflicht beginnt
                                ; von vorne

END

von Amy18146 (Gast)


Lesenswert?

eine frage habe ich noch:

wenn ich timer0 mode 2 benutzen möchte, wie berechne ich den 
nachladewert für TH0?

vielen dank.

von 8051 (Gast)


Lesenswert?


von Wilhelm F. (Gast)


Lesenswert?

Amy18146 schrieb:
> eine frage habe ich noch:
>
> wenn ich timer0 mode 2 benutzen möchte, wie berechne ich den
> nachladewert für TH0?
>
> vielen dank.

Bei einem Timerinterrupt für Timer 0 im 16-bit-Mode kann ich dir helfen, 
daß der Timer im Interrupt wirklich absolut exakt nachgeladen wird:
1
FREQUENCY     EQU   18000/8       ; Quarz in kHz /8 = Slow-Down-Mode
2
RELOAD        EQU   0 - FREQUENCY/3*5 + 7
3
4
für einen Interrupt alle 20ms
5
6
    CLR     EAL
7
    CLR     TR0            ;Berechnung des tatsaechlichen
8
    MOV     A,#LOW(RELOAD) ;neuen Start-Wertes fuer den Timer
9
    ADD     A,TL0          ;praeziser Abstand msec 
10
    MOV     TL0,A          ;der Interrupt-Signale
11
    MOV     A,#HIGH(RELOAD)
12
    ADDC    A,TH0
13
    MOV     TH0,A
14
    SETB    TR0            ;Timer nach dem Laden erneut starten
15
    SETB    EAL

Hier wird der Timer in jedem Interrupt gestoppt, nachgeladen, und wieder 
gestartet.

Die 7 sind die 7 Takte, in denen der Timer gestoppt ist, und nachgeladen 
wird.

Ich hatte diese Befehlssequenz jahrelang in einer DCF77-Uhr, lief gut.

Die Ersetzung RELOAD ist ein 16-bit-Wert, der irgendwo mit Defines 
definiert wird. Das ist aber bei jedem Assembler anders.

Auch auf einem C-Compiler geht die Nachladung nur exakt so. Ich habe in 
den 8051-Projekten deshalb immer noch ein Assembler-File drin, oder 
Inline-Code.

von Amy18146 (Gast)


Lesenswert?

hm...so ganz ist mir das nicht klar...
also ich dachte jetzt erkannt zu haben, dass die berechnung des 
reloadwertes folgendermaßen aussieht:

Reloadwert:
2^8=256, da nur TH0 benutzt wird. TL0 ist im mode2 nur zum Wert halten 
da.
f-osz 0= 12MHz

f-osz/12= 10000/ 256= 39,0625 (=rund 40)

10000/40= 250, daraus ergibt sich folgendes:

256-250 = 6 dez (Reloadwert)

oder habe ich da etwas falsch verstanden????

von Wilhelm F. (Gast)


Lesenswert?

Was willst du mit dem Mode 2? Eine sehr hohe Interruptfrequenz, die das 
ganze Programm ausbremst?

Schau dir die von mir gepostete Nachladesequenz an. Die geht bei 12MHz 
für eine 1ms, 5ms, 10ms, glatte Werte.

von Amy18146 (Gast)


Lesenswert?

Hallo,

das Lauflicht soll auch mit Timer0 Mode2 realisiert werden. Das ist ein 
Teil einer Aufgabe!!!

Die Berechnung für Mode2 ist so richtig oder?

Vielen Dank.

von Wilhelm F. (Gast)


Lesenswert?

Amy18146 schrieb:

> Die Berechnung für Mode2 ist so richtig oder?

Jep, sieht gut aus. Mit dem Wert 6 bekommst du 250µs-Intervalle.

Da fehlt dann in der Interruptroutine nur noch eine Zählvariable, mit 
der man die längeren Zeiten realisiert.

von Amy18146 (Gast)


Lesenswert?

Vielen Dank für eure Hilfe :D

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.