Forum: Mikrocontroller und Digitale Elektronik c515c - Timer


von Lens (Gast)


Lesenswert?

Hi,

Ich will, dass jede Sekunde der Status eines Pins wechselt, also im 
Sekundentakt. Die CPU hat einen Takt von 10MHz. Dafür hab ich diese 
Formel entwickelt:
1
if(num_cnt_max < (10000000/6/65535)) {
2
 // Status des Pins wechseln
3
}

Meine Überlegung zur Formel:
/6 (=Gesamtzählungen in einer Sekunde): Weil ein Maschinenzyklus aus 6 
Takten(Phasen) besteht
/65535 (wie oft bis 65535 zählen, bis auf 1s komme)

Das ganze ist in C programmiert. Natürlich ist sind Fehlertoleranzen mit 
drinnen wegen den anderen Befehlen.

Kann mir jemand bitte die Richtigkeit bestätigen`oder mir einen Tipp 
geben?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Lens schrieb:
> Kann mir jemand bitte die Richtigkeit bestätigen
Vorneweg eine Frage: Woher kommt num_cnt_max?

> 10000000/6/65535
Welchen Wert soll der Compiler da ermitteln?
Welche Wortbreite haben Konstante bei deinem Compiler?
(Ich würde auf jeden Fall mit 10000000UL rechnen...)

> Weil ein Maschinenzyklus aus 6 Takten(Phasen) besteht
Ich habe den Verdacht, du willst einen Softwarezähler eine Zeit machen 
lassen. Ist das so?
Falls ja: wieviele Maschinenzyklen braucht dein C-Code für eine 
Schleife?

> Natürlich ist sind Fehlertoleranzen mit drinnen wegen
> den anderen Befehlen.
Kann gut sein, dass "die anderen Befehle" zigmal mehr Rechenzeit 
brauchen als deine Schleifenverwaltung...

> `oder mir einen Tipp geben?
Genaue Zeiten macht man mit Hardwarezählern bzw. Timern.

von Lens (Gast)


Lesenswert?

Hi,

1. num_cnt_max ist die Anzahl der aufgetretenen Overflows. D. h. jedes 
Mal wenn der Timer ein Interrupt auslöst wird in der 
Interrupt-Service-Routine num_cnt_max (was int ist) hochgezählt.
3. Also wie schon unter 1 erwähnt, bin ich in meinem Programm in einer 
Endlosschleife, nur wenn der Timer ein Interrupt auslöst, geht es in die 
Interrupt Service Routine, wo "num_cnt_max" hochgezählt wird.
Mein Code, etwas ausführlicher:
1
                int num_cnt_max = 0; // Wie oft schon bis 65535 gezählt
2
int pin_is_on = -1;
3
4
void timer_ISR (void) interrupt 1
5
{
6
  num_cnt_max++;
7
8
  /* Unsere CPU hat 10MHz. 10MHz / 6 = Gesamtzählung in 1s.
9
   * 10MHz / 6 / 65535 = 25 (Wie oft bis 65535 zählen, bis auf 1s 
10
         * komme).
11
        */
12
  if(num_cnt_max < 25)
13
   return;  
14
15
  num_cnt_max = 0;
16
  
17
  if(pin_is_on == -1) {
18
    pin_is_on = 1;
19
    P1_0 = 0;
20
  }
21
  else {
22
    pin_is_on = -1;
23
    P1_0 = 1;
24
  }
25
}

von Karl H. (kbuchegg)


Lesenswert?

Lens schrieb:

> 1. num_cnt_max ist die Anzahl der aufgetretenen Overflows. D. h. jedes
> Mal wenn der Timer ein Interrupt auslöst wird in der
> Interrupt-Service-Routine num_cnt_max (was int ist) hochgezählt.

Gut. das ist schon mal die halbe Miete.

Allerdings: was interessiert dich dann die 'Anzahl der Maschinenzyklen'? 
Je nachdem wie dein Timer eingestellt ist, hast du eine bestimmte Anzahl 
von Overflows in der Sekunde und diese Anzahl zählst du einfach ab.

Braucht der Timer wirklich 6 Maschinenzyklen bis er um 1 weiterzählt? 
Möglich ist es. Aber du hast das Datenblatt zum µC.

von Lens (Gast)


Lesenswert?

Hi Karl,

Erstmal Danke. Wirklich super!
Aber eine Frage: Wie sonst soll ich denn feststellen können ob eine 
Sekunde jetzt um ist. Ich bin im Timer-Mode-1. Ist ein 16-Bit-Zähler. 
Der Timer löst ja immer dann ein Interrupt aus, wenn ein Overflow 
passiert. Wie sonst soll ich das machen? Es steht ja nirgendwo, dass 
jetzt eine Sekunde vorbei ist.

Kannst du mir da einen Tipp geben?

von Karl H. (kbuchegg)


Lesenswert?

Lens schrieb:
> Hi Karl,
>
> Erstmal Danke. Wirklich super!
> Aber eine Frage: Wie sonst soll ich denn feststellen können ob eine
> Sekunde jetzt um ist.

Wie schnell zählt der Timer?

Das ist die einzig entscheidende Frage.

Wieviele Maschinenzyklen welcher Befehl bzw. welche C-Anweisung braucht, 
ist dazu völlig irrelevant, denn der Timer zählt für sich alleine! Das 
ist ja der ganze Trick bei Timern - dass sie völlig losgelöst vom 
restlichen Programm arbeiten.

von Karl H. (kbuchegg)


Lesenswert?

MIttlerweile hab ich auch das Datenblatt zum µC gefunden und der Timer 0 
zählt im 16 Bit Modus mit 1/6 der Taktfrequenz.

Also stimmt das so, wie du das gemacht hast.

von Lens (Gast)


Lesenswert?

Yesssssssssss!!!!

Danke!! Das löst echt Glücksgefühle aus :). Nur noch eine Bitte um einen 
Tipp:
Du sagst, der Timer ist entkoppelt von allem. Das ist mir klar, aber 
was, wenn nun die Interrupt Service Routine so viel erledigen muss, dass 
während es noch nicht abgearbeitet ist, schon der nächste Overflow 
eintritt?

von Karl H. (kbuchegg)


Lesenswert?

Lens schrieb:

> was, wenn nun die Interrupt Service Routine so viel erledigen muss, dass
> während es noch nicht abgearbeitet ist, schon der nächste Overflow
> eintritt?


Wenn du zum abarbeiten eines Dokuments (Formular, Arbeitsauftrag, ...) 
ganze 2 Stunden brauchst, dein Chef dir aber alle 1 Stunde ein neues 
Dokument auf den Schreibtisch legt, was wird dann passieren?

-> du kommst mit der Arbeit nicht mehr hinterher und die 
Dokumentanmappen werden sich auf deinem Schreibtisch stapeln. Ist kein 
Platz mehr auf dem Schreibtisch, dann werden Dokumentenmappen magisch 
verlorengehen.


Bei einem µC ist das auch nicht anders als im realen Leben. So ein µC 
kann ja auch nicht zaubern.

von Lens (Gast)


Lesenswert?

Es ist selten, dass einer so gut Antworten gibt wie du. Deswegen möcht 
ich die Gelegenheit nutzen um dir eine letzte Frage zu stellen:
Im Timer-Mode-0, gibt es einen 5-Bit-Prescaler(Lower-Byte des 
TLx-Registers). Es wird als "divide-by-32-prescaler" bezeichnet. Kann 
ich diesen prescaler selbst bestimmen von 1 bis 32, oder ist schreibt 
der Timer von selbst 32 in TLx? Steht in der Herstellerbeschreibung 
nicht drinnen.

wirklich danke für deine Mühen!

von Karl H. (kbuchegg)


Lesenswert?

Lens schrieb:
> Es ist selten, dass einer so gut Antworten gibt wie du. Deswegen möcht
> ich die Gelegenheit nutzen um dir eine letzte Frage zu stellen:
> Im Timer-Mode-0, gibt es einen 5-Bit-Prescaler(Lower-Byte des
> TLx-Registers). Es wird als "divide-by-32-prescaler" bezeichnet. Kann
> ich diesen prescaler selbst bestimmen von 1 bis 32,

So wie ich das Datenblatt verstehe, ist dieser Presclaer fix auf 32 
eingestellt. d.h. du hast ausgehend von der Quarz Rate einen Faktor 6*32

von Lens (Gast)


Lesenswert?

Einfach super! Danke dir!

von Lens (Gast)


Lesenswert?

Ich möcht nochmal Danke sagen. Das ist echt super! Du hast grad einige 
Knoten in meinem Hirn aufgelöst :). Danke!

von Garden (Gast)


Lesenswert?

Zur Timerprogrammierung von 8051 gibt es hier einige Videos:

http://et-tutorials.de/4458/timer-interrupt-des-8051-mikrocontrollers/

von Häsch Define (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

> So wie ich das Datenblatt verstehe, ist dieser Presclaer fix auf 32
> eingestellt. d.h. du hast ausgehend von der Quarz Rate einen Faktor 6*32

Gibt es irgendwo einen Link auf ein Datenblatt des C515C?

Dann kann ich evtl. was dazu sagen. Denn ich gehe mal davon aus, daß 
dieser µC einen Standard-8051-Core hat, wie auch der Vorgänger des 
C515C, der SAB80535.

von Karl H. (kbuchegg)


Lesenswert?

Häsch Define schrieb:
> Karl Heinz Buchegger schrieb:
>
>> So wie ich das Datenblatt verstehe, ist dieser Presclaer fix auf 32
>> eingestellt. d.h. du hast ausgehend von der Quarz Rate einen Faktor 6*32
>
> Gibt es irgendwo einen Link auf ein Datenblatt des C515C?

Ich beziehe mich auf das hier
http://www.infineon.com/dgdl/c515_ds_0203_1.pdf?folderId=db3a304412b407950112b408e8c90004&fileId=db3a304412b407950112b43613d76467

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?


von Häsch Define (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Ich beziehe mich auf das hier
> http://www.infineon.com/dgdl/c515_ds_0203_1.pdf?fo...

Danke. Alles, was ich sehe, ist, daß die Timer mit dem 8051 gleich sind, 
jedoch die doppelte Frequenz haben. Der Quarztakt wird anstatt durch 12 
nur durch 6 geteilt.

Mit dem 5-bit-Prescaler hat man nichts zu tun. Das ist noch ein altes 
Relikt aus der 8048-Zeit, um mit diesem noch etwas kompatibel zu sein.

Also: Timer 0 oder 1 im Modus 1 (16 bit) betreiben, dann wird das was.

Eine genaue Sekunde bekommt man mit den 10MHz nicht hin, weil die 
Sekunde keine glatte Anzahl Zähltakte ergibt. Man muß da mit einer sehr 
geringen Abweichung von etwa 10ppm leben. Auch ist der Reload im 
Interrupt etwas trickreicher, wenn man es ganz präzise haben möchte.

Irgend eine Interruptrate mit (ungefähr) 25ms sollte leicht hin zu 
bekommen sein, dann hat man 20 Überläufe die halbe Sekunde, wenn es im 
Sekundentakt blinken soll. Dann wird die Interruptfrequenz auch nicht zu 
arg hoch.

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.