Hallo zusammen,
ich stehe grad etwas auf dem Schlauch. Ich besitze ein AT89C51ED2
Testboard mit einem 29,4912 MHz Quarz an Xtal. Normalerweise kommt doch
der Teiler zum Einsatz wenn ich die Zeit ausrechnen möchte. Im
Datenblatt habe ich einen Teiler von 2 bzw. 6 gefunden. Welches ist der
Standard ? Aber egal welcher, ich komme nach der Berechnung immer auf
1µs. Wenn ich in der ISP eine Schleife mit 100 Durchgängen mache, und
einen Port inkrementiere, sollten laut Berechnung 6,5s pro Inkrement
rauskommen, bei mir scheint es irgendwie schneller zu sein...
Andes schrieb:> Hallo zusammen,>> ich stehe grad etwas auf dem Schlauch. Ich besitze ein AT89C51ED2> Testboard mit einem 29,4912 MHz Quarz an Xtal. Normalerweise kommt doch> der Teiler zum Einsatz wenn ich die Zeit für den Timer 0 ausrechnen möchte. Im> Datenblatt habe ich einen Teiler von 2 bzw. 6 gefunden. Welches ist der> Standard ? Aber egal welcher, ich komme nach der Berechnung immer auf> 1µs. Wenn ich in der ISP eine Schleife mit 100 Durchgängen mache, und> einen Port inkrementiere, sollten laut Berechnung 6,5s pro Inkrement> rauskommen, bei mir scheint es irgendwie schneller zu sein...
Andes schrieb:> Aber egal welcher, ich komme nach der Berechnung immer auf> 1µs.
Zeig mal diese Berechnung.
> Wenn ich in der ISP eine Schleife mit 100 Durchgängen mache
Was ist ISP?
Bei einem 6-Cycle-Core komme ich auf 13,3 Sekunden, bei 2-Cycle auf 4,4
Sekunden.
Sind es die 4,4 Sekunden im Vergleich zu 6,5 Sekunden?
Ich kenne eigentlich nur Standard-8051 mit 12-Cycle-Core, aber das kann
ja nichts viel anderes sein.
Andes schrieb:> 29,4912 MHz : 6 = 4,9152 MHz * 10 hoch -6 = 1µs> 1s * 65536 = 0,065s * 100 = 6,5s
Batterie vom Taschenrechner leer??
Im X2-Modus benötigt der ED2 6 Takte pro Maschinenzyklus. Also dauert
ein Maschinenzyklus 6/29,4912 * 10e6 Hz = 203,45ns
Mit 65536 MZ benötigt ein Timerdurchlauf 203,45ns*65536 = 13,33ms.
Deine 1000 Überläufe der ISR dauern daher 13,33 s.
Ohne X2-Modus ist die Zeit doppelt so lange, weil da der ED2 12 Takte/MZ
beötigt.
Andes schrieb:> wie kommst Du auf 13,3s bzw, 4,4s ?
Ganz einfach: Ich teile die Quarzfrequenz durch 12, dann habe ich die
Taktzyklenzahl für einen Standard-8051. 2,457.600 MHz. Die teile ich
noch mal durch die natürliche Timer-Überlaufzahl 65536, sind 37,5 Hz.
Das ergibt mit einem frei laufenden Timer und Teiler 1000 beim
12-Cycle-Core eine Zeit von 26,66 Sekunden, beim 6-Cycle-Core (Teiler
durch 2) 13,33 Sekunden, beim 2-Cycle-Core (Teiler durch 6) die 4,4
Sekunden.
D.h. mit dem 29,4912 MHz Quarz wird es schwierig sein, genau 1s zu
programmieren ?
In der Schleife sollte 10 stehen, nicht 1000, aber der Port aber über
60s um komplettt zu inkrementieren.
Andes schrieb:> D.h. mit dem 29,4912 MHz Quarz wird es schwierig sein, genau 1s zu> programmieren ?
Welchen Timer verwendest du?
Man kann Timer übrigens auch im Interrupt mit einem berechneten
Vorgabewert nach laden. Das muß nicht 65536 sein, sondern z.B. 50000,
oder 34597, oder sonst was. Da mußt du eine geeignete Berechnung suchen.
Wie dein Quarz mit exakten Timings funktioniert, habe ich allerdings
noch nicht zu rechnen versucht. 12MHz und 18MHz liefen für exakte
Sekunden bei meinen 8051-ern immer einwandfrei.
Wilhelm F. schrieb:> Man kann Timer übrigens auch im Interrupt mit einem berechneten> Vorgabewert nach laden. Das muß nicht 65536 sein, sondern z.B. 50000,> oder 34597, oder sonst was. Da mußt du eine geeignete Berechnung suchen.
Wenn ich nicht irre, kann der nur count up. Man muss die Differenz zu
65... bilden.
longlife schrieb:> Wenn ich nicht irre, kann der nur count up. Man muss die Differenz zu> 65... bilden.
Das macht aber nichts. Das berechnet der Compiler. Man schreibt dann
eben:
#define reload 65536-50000.
Andes schrieb:> dann werd ich mal den 29 MHz gegen einen 12 MHz Quarz tauschen
Nee. Würde ich jetzt nicht, weil die Quarzfrequenz schon hoch ist.
Versuch erst mal, heraus zu finden, wie der maximale Fehler mit deinem
Quarz ist. Das kann sehr gut gehen. Denn Quarze haben selbst auch noch
Frequenzfehler, oft im Bereich 50ppm.
Umd im schlimmsten Fall kann man auch noch per Software korrigieren.
Z.B. den Fehler alle X Interrupts mit einer Korrektur des Nachladewertes
um +/-1 korrigieren.
Wilhelm F. schrieb:> Das ergibt mit einem frei laufenden Timer und Teiler 1000 beim> 12-Cycle-Core eine Zeit von 26,66 Sekunden, beim 6-Cycle-Core (Teiler> durch 2) 13,33 Sekunden, beim 2-Cycle-Core (Teiler durch 6) die 4,4> Sekunden.
Was hast Du mit einem frei laufenden Timer und Teiler 1000 gemeint ? Wie
kommt man auf den teiler 1000
Wilhelm F. schrieb:> longlife schrieb:>>> Wenn ich nicht irre, kann der nur count up. Man muss die Differenz zu>> 65... bilden.>> Das macht aber nichts. Das berechnet der Compiler. Man schreibt dann> eben:>> #define reload 65536-50000.
Mein Fahrrad kann rückwärts fahren. Ich setze mich einfach auf den
Lenker und trete in die Pedale. :-\
Wilhelm F. schrieb:> Ich teile die Quarzfrequenz durch 12, dann habe ich die> Taktzyklenzahl für einen Standard-8051. 2,457.600 MHz.
Nachtrag:
So wie es aus sieht, ist dein Quarz also auch noch ein richtiger
Baudratenquarz für den UART. Mit einer Veränderung des Quarzes auf
exaktes Zeit-Timing verschlimmbesserst du nur.
Bei einem für Timings exakten Quarz z.B. 12 MHz für den 8051 erreicht
man beim UART nicht mehr die 9600 Baud, sondern 9615 Baud. Bei den 0,2%
Abweichung läuft das aber auch noch eben so.
Eine exakte Übereinstimmung dieser µC für Baudrate und Timing erreicht
man direkt auf den ersten Blick nicht.
Hallo,
den UART brauche ich wahrscheinlich eh nicht so schnell, mir wäre lieber
eine genaue Zeit z.Bsp. beim Blinken von LED´s. Ich möchte später z.Bsp.
ein Modellbauservo ansteuern, das für Linksanschlag eine Zeit von ca.
1ms braucht von der Mittelstellung heraus. Da muß ich die PWM´s
entsprechend konfigurieren...
Andes schrieb:> Hallo,>> den UART brauche ich wahrscheinlich eh nicht so schnell, mir wäre lieber> eine genaue Zeit z.Bsp. beim Blinken von LED´s. Ich möchte später z.Bsp.> ein Modellbauservo ansteuern, das für Linksanschlag eine Zeit von ca.> 1ms braucht von der Mittelstellung heraus. Da muß ich die PWM´s> entsprechend konfigurieren...
Mit dem Teiler durch 2 hast du die halbe Quarzfrequenz als Timertakt,
über 14 MHz. Damit sollten sich Werte für eine Millisekunde einstellen
lassen, die so gut sind, daß sie auch nur im Bereich der Quarztoleranzen
liegen.
Denn der Quarz ist auch nicht exakt genau.
Meine schlimmste Schaltung, die aber einwandfrei dimensioniert war,
hatte eine Quarztoleranz von schlaffen 690ppm. Das waren ausgerechnet
auch noch bei der DCF77-Uhr ohne Funksignal mehr als eine Minute
Falschanzeige pro Tag! So schlimm ging nicht mal meine rein mechanische
Kommunions-Armbanduhr von 1968 falsch. Der Quarz war auch nicht aus
einem Nobelshop für Industrieanwender, sondern von den üblichen
Verdächtigen Bastelshops.
Hallo Wilhelm,
mit dem Teiler 2 meinst Du sicherlich das, was sonst mit Teiler 12
gerechnet wird ?
Habe hier wohl eine Endlosschleife gebastelt. Ich möchte aber, dass der
Port nur einmal inkrementiert wird und dann wieder zum Hauptprogramm
zurückspringt. wWe heißt der Befehl, um die ISR zu verlassen ?
void ISR_Timer (void) interrupt 1
{
TH0 = 0xF0;
TL0 = 0x1B;
i++;
if(i==1000)
{
P2 = P2+1;
i=0;
}
}
Andes schrieb:
Hallo,
mit dem Teiler 2 meinst Du sicherlich das, was sonst mit Teiler 12
gerechnet wird ?
Habe hier wohl eine Endlosschleife gebastelt. Ich möchte aber, dass der
Port nur einmal inkrementiert wird und dann wieder zum Hauptprogramm
zurückspringt. wWe heißt der Befehl, um die ISR zu verlassen ?
void ISR_Timer (void) interrupt 1
{
TH0 = 0xF0;
TL0 = 0x1B;
i++;
if(i==1000)
{
P2 = P2+1;
i=0;
}
}
Andes schrieb:> Hallo Wilhelm,>> mit dem Teiler 2 meinst Du sicherlich das, was sonst mit Teiler 12> gerechnet wird ?
Genau. Modernere 8051-Derivate haben anstatt einen 12-Cycle-Core auch
mal einen 2-Cycle-Core.
Wobei: Ich kenne deinen µC genau nicht, habe kein Datenblatt. Ich weiß
nur, daß es ein modernerer 8051 ist.
> Habe hier wohl eine Endlosschleife gebastelt. Ich möchte aber, dass der> Port nur einmal inkrementiert wird und dann wieder zum Hauptprogramm> zurückspringt. wWe heißt der Befehl, um die ISR zu verlassen ?>> void ISR_Timer (void) interrupt 1> {> TH0 = 0xF0;> TL0 = 0x1B;>>> i++;> if(i==1000)> {> P2 = P2+1;> i=0;> }>> }
ISR verlassen, da brauchst du gar nichts zu machen, der C-Compiler wird
das RETI am Ende selbst anfügen.
Dazu kannst du ja mal in die Listings schauen.
So wie es jetzt aus sieht, wird dein Port alle 1000 Interrupts
inkrementiert.
Du müßtest für das Hauptprogramm zur Erkennung ein Flag nach 1000
Increments im Interrupt setzen, als Merker. Damit das Hauptprogramm
sieht, daß die 1000 Increments um sind. Im Hauptprogramm den Merker
wieder löschen.
Der Merker kann ein ganzes Byte sein, z.B. Char, aber weil 8051-er auch
einzelne Bits steuern können, auch nur ein bit.
Wenn du eine ganz exakte Timernachladung auf den Takt genau brauchst,
das geht in C nicht immer ganz einwandfrei, aber Assembler, dann schaue
ich da auch noch mal extra nach. Denn der µC und der Timer laufen ja
über Überträge auch weiter, das kann böse Fehler geben. Man muß da ein
Stückchen Nachladung dann in Inline-Assembler machen, oder im externen
eingebundenen Assemblerfile.
Dazu mußt du dir klar machen, wie die Hardware-Maschine läuft,
Interupt-Latenzzeiten.
Zum µC: Hast du da mal ein Datenblatt oder Link? Vielleicht komme ich da
schnell durch, heute nicht mehr, eher morgen beim Kaffee.
Andes schrieb:> Müßte das Flag im Hauptprgramm ungefähr so aussehen: if (TF==1000) ??> Und wie meinst Du das mit dem Merker ?
Definiere mal global ein "volatile unsigned char post". Die Variable
post kannst du in der Initialisierung 0 setzen, und im Interrupt bei
Erreichung von 1000 auf 1 setzen. Die 1 kannst du im Hauptprograamm
auswerten, erkennen, daß ein Interrupt da war, und sie dort wieder auf 0
zurück setzen, bis nächstes mal.