Forum: Mikrocontroller und Digitale Elektronik Fragen zum Timer beim 8051 bzw. C515C


von C515C (Gast)


Lesenswert?

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...

von Matthias Kölling (Gast)


Lesenswert?

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.

von C515C (Gast)


Lesenswert?

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 :-/

von Gast (Gast)


Lesenswert?

Ea ist einfach besser, wenn du das Programm postest.

von Carlos (Gast)


Lesenswert?

Hallo,
stell mal deinen Code ein, dann kam man vielleicht etwas mehr dazu 
sagen.

Gruß

Carlos

von C515C (Gast)


Lesenswert?

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

von C515C (Gast)


Lesenswert?

Natürlich wird r0 auch wieder auf 0 gesetzt, die Zeile hab ich 
unterschlagen sorry

von Matthias Kölling (Gast)


Lesenswert?

Punkt1: Du brauchst den Timer nicht neu zu initialisieren, da er 
weiterrennt.
Punkt2: R0 wir bei erreichen der 25 nicht genullt.

von schudi (Gast)


Lesenswert?

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

von Matthias Kölling (Gast)


Lesenswert?

Deswegen zählt er bis 25

von schudi (Gast)


Lesenswert?

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

von schudi (Gast)


Lesenswert?

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

von APW (Gast)


Lesenswert?

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 ?

von C515C (Gast)


Lesenswert?

Beim C515C ists tatsächlich 1/6. Meine programmierte Sekunde dauert 
so... 20ms ;-)?!

von C515C (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.