Hallo!
Ich versuche per Timer ganze Sekunden zu zählen. Dafür hab ich für Timer
1 M1 und M0 auf "M1=0 M0=1" gesetzt, so das ich einen 16 Bit-Zähler
habe. TH1 und TL1 werden somit kaskadiert verwendet, so das ich bis
65536 zählen kann.
Jetzt meine Rechnung:
Laut Angabe aus einem Datenblatt soll der C515C bei 10 MHz Taktfrequenz
den Timer alle 0.6us inkrementieren.
Damit ich auf eine Sekunde komme, brauche ich also 1s/(0.6us)=1.666.667
Zählschritte. Nach 65536 Zähl-Schritten bekomme ich jeweils einen
Überlauf des Timers, also einen Interrupt.
D.h. nach ca. 1.666.667/65536 = 25 Interrupts ist eine Sekunde
verstrichen.
Ist das soweit richtig?! Bei mir kommt der Interrupt viel zu oft, das
sind im Leben keine Sekunden und ich finde den Fehler nicht...
Daran kann es nicht liegen, da beim 8051/C515C das TF1 (Timer 1 Overflow
Flag) automatisch von der Hardware resetted wird, wenn der Prozessor in
die Unterruptroutine springt :-/
Okay, also scheint es an meiner Rechnung ja erstmal nix auszusetzen zu
geben. Programm ist in Assembler, hier die wesentlichen Auszüge:
Timer initialisierung (ja, gerade nicht schön I know)
1
InitTimer1:
2
;
3
; 7 gate: 0 weil timer nicht vom gate sondern nur vom OSC abhängig sein soll
4
; 6 C/!T: muss 0 sein, damit der OSC als Timer dient und kein externer Pin
5
; 5 4 M1M0-Combo: 0 1 -> 16 bit timer TH1 und TL1 werden kaskadiert, so das länger gezählt werden kann
6
mov tmod,#00010000b
7
8
9
clr tr1 ; Timer anhalten, um neue Werte schreiben zu können
10
11
; Timer initalisieren, es soll immer von 0-65k gezählt werden
12
mov th1,#0x00
13
mov tl1,#0x00
14
setb tr1 ; Timer 1 starten (Run)
15
ret
Interrupt-Routine des Timers, die auch aufgerufen wird
1
g_Intr_Counter1:
2
; Akku wird normalerweise gesichert, genau wie die Registerbänke, hier gehts gerade ums testen
3
push psw
4
5
6
; Eigentliche Interruptbehandlung
7
;--------------------------------
8
9
cjne r0,#0x19, bla ; 25 Dezimal,d.h. erst nach 25 Interrupts a inkrementieren
10
11
inc a
12
13
call serout ; Akkuinhalt auf serieller Schnittstelle ausgeben
14
15
call InitTimer1 ; Timer wieder neu initialisieren (Methode von oben)
Hallo,
der C515C teilt laut Datenblatt die Oszillatorfrequenz durch 6.
Bei 10 MHz Taktfrequenz ergibt sich dann eine Taktzykluszeit von 0,6 µs
wie Du richtig geschrieben hast. Weil bei einem 16 Bit-Timer bis 65536
Interrupts gezählt werden können, bis er überläuft, ergibt sich daraus
eine maximale Verzögerungszeit von 39,3216 ms. Willst du mehr (z.B. 1 s)
mußt du bei jedem Timerinterrupt eine zusätzliche Variable hochzählen
und abfragen!
mfg
Lothar
Hallo,
ich hatte meine Antwort schon formuliert, als der Codeausschnitt
noch nicht sichtbar war :-(
Aber meines Wissens ist der Timer-Counter ein Abwärtszähler und löst den
Interrupt aus, wenn er 0 erreicht. In diesem Beispiel müsste er meines
Erachtens deshalb auf auf 65535 initialisiert werden.
Wird er auf 0 initialisiert macht er immer sofort einen Interrupt.
Kein Wunder, daß dann die Zeit zu kurz ist, weil nur 25 Takte auf r0
gezählt werden, wobei r0 aber in der Tat nirgendwo resettet wird!
mfg
Lothar
sorry, ich habe Müll geschrieben!
Der Timer wird natürlich bis zum Überlauf hochgezählt (nicht runter) und
macht den Interrupt, wenn er 0 wird.
Schäm....
mfg
Lothar
Sagt mal, ist der C515C was Anderes als ein C515 ?
Ich programmiere hier gerade auf einem C535 und hier ist der Timertakt
F_Osz/12.
Aber dann müsste der Int weniger oft kommen als berechnet, und bei dir
kommt er ja zu oft.
Wie lange dauert eigentlich deine programmierte Sekunde ?
Okay Problem gelöst: Es gab gar kein Problem.
Ich hab das nicht im realen Umfeld getestet sondern mit uVision. Dort
läuft alles schneller ab, als in Wirklichkeit. Eine Sekunde entsprach
dort ca 60 Sekunden. Also es passt alles, nach 1.0224s lande ich beim
Breakpoint :-)