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?
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.
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
intnum_cnt_max=0;// Wie oft schon bis 65535 gezählt
2
intpin_is_on=-1;
3
4
voidtimer_ISR(void)interrupt1
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
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.
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?
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.
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.
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?
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.
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!
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
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.
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.