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...
Vielleicht ist das interrupt request flag von Hand zu löschen. Wenn man das dann vergisst, wir die ISR nach dem Verlassen sofort wieder angesprungen.
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 :-/
Hallo, stell mal deinen Code ein, dann kam man vielleicht etwas mehr dazu sagen. Gruß Carlos
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) |
16 | bla: |
17 | inc r0 |
18 | |
19 | ;-------------------------------- |
20 | pop psw |
21 | reti |
Natürlich wird r0 auch wieder auf 0 gesetzt, die Zeile hab ich unterschlagen sorry
Punkt1: Du brauchst den Timer nicht neu zu initialisieren, da er weiterrennt. Punkt2: R0 wir bei erreichen der 25 nicht genullt.
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 ?
Beim C515C ists tatsächlich 1/6. Meine programmierte Sekunde dauert so... 20ms ;-)?!
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 :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.