Forum: Mikrocontroller und Digitale Elektronik AT89C51ED2 und Timer


von Andes (Gast)


Lesenswert?

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

von Andes (Gast)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

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?

von Andes (Gast)


Lesenswert?

ISP = Interrupt Service Routine.

Berechnung:

void Timer0(void) interrupt 1
{
    i++;
    if(i == 1000)
        {
            P2 = P2 + 1;
            i = 0;
        }
}

29,4912 MHz : 6 = 4,9152 MHz * 10 hoch -6 = 1µs
1s * 65536 = 0,065s * 100 = 6,5s

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

Hallo,

wie kommst Du auf 13,3s bzw, 4,4s ?

von Bernhard S. (b_spitzer)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

Hallo,

dann werd ich mal den 29 MHz gegen einen 12 MHz Quarz tauschen

von longlife (Gast)


Lesenswert?

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.

von longlife (Gast)


Lesenswert?

Und es heisst ISR.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

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

von longlife (Gast)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

Andes schrieb:

> Wie
> kommt man auf den teiler 1000

Das ist der in deiner gezeigten Interruptroutine, mit der Variablen i.

von Peter D. (peda)


Lesenswert?

Wenn ich das richtig erinnere, geht bei 30MHz nur die 1/12 Teilung.

von Andes (Gast)


Lesenswert?

Hallo nochmal,

aber ich könnte trotzdem für den Anfang mal problemlos eine 12MHz Quarz 
einlöten und damit testen...

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

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;
      }

}

von Andes (Gast)


Lesenswert?

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;
       }

}

von Wilhelm F. (Gast)


Lesenswert?

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.

von Andes (Gast)


Lesenswert?

Anbei der Link zum Datenblatt:

http://www.alldatasheet.com/datasheet-pdf/pdf/82697/ATMEL/AT89C51ED2.html


Müßte das Flag im Hauptprgramm ungefähr so aussehen: if (TF==1000) ??
Und wie meinst Du das mit dem Merker ?

von Wilhelm F. (Gast)


Lesenswert?

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.

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.