125 KHz Rechtecksignal erzeugen mit PIC - erreiche nur 16KHz

OP Persönliche Seite #977294
Lesenswert?

Hallo zusammen,

ich habe ein kleines Programm für einen PIC 16F84A geschrieben in C.

Das soll mir einfach ein Rechteckimpuls mit der Frequenz 125 KHz 
erzeugen. Leider erreiche ich laut Oscar nur 16,66 KHz.
Ausserdem ist die Ration nicht ganz 50:50, der Low-Bereich ist ein wenig 
kürzer als der High-Bereich.

Kann mir jemand einen Tip geben woran das liegen mag?

Danke schonmal.
 Tobias
Angehängte Dateien:
Persönliche Seite #977317
Lesenswert?

> Unsymmetrisches Signal

Statt
1
    if(RB1 == 0)
2
      RB1 = 1;
3
    else if(RB1 == 1)
4
      RB1 = 0;

schon mal
1
    RB1 ^= 1;

benutzt, um den Portpin zu toggeln?

> Frequenz

1/ Oszilloskop richtig kalibriert, Timebase richtig eingestellt und 
korrekt abgelesen?

2/ Mit welchem Takt läuft der PIC? Reicht die Rechenleistung bei dieser 
Taktrate für 125 kHz aus? Das Aufrufen der Interruptroutine und die 
Abarbeitung benötigt Rechenzeit.

Die maximal mögliche Togglefequenz bei gegebener Taktrate könntest du 
herausfinden, indem du den Timer mal weglässt und die Hauptschleife so 
machst:
1
    while (1)
2
    {
3
      RB1 ^= 1;
4
    }

3/ Stimmt der Prescaler und der Vorladewert von TMR0?

TMR0 = 255 heisst ja, dass der nächste Timertakt bereits den 
Overflow-Interrupt auslöst. Im Interrupt kommt dann der Reset auf 255. 
D.h. du arbeitest zusammen mit dem Prescaler im schnellstmöglichen 
Interruptbetrieb! Ich schätze Punkt 2/ kneift dich.
#977337
Lesenswert?

Tobias John wrote:
> Hallo zusammen,
Hallo ;-)

> Das soll mir einfach ein Rechteckimpuls mit der Frequenz 125 KHz
> erzeugen. Leider erreiche ich laut Oscar nur 16,66 KHz.
Viele (alle?) PICs nutzen als Zählertakt nicht die Quarzfrequenz, 
sondern nur ein Viertel davon.
Mach doch mal  genauere Angaben bzgl. Quarztakt.

> Ausserdem ist die Ration nicht ganz 50:50, der Low-Bereich ist ein wenig
> kürzer als der High-Bereich.
Das liegt an deinem Code.
Für den Low-Bereich wird nur "if RB1 == 0" abgearbeitet; für High "if 
RB1 == 0" und "if RB1 == 1".

Das kannst du aber so lösen indem du schreibst
RB1 = ~RB1;

Bist du sicher, dass dein Timer rückwärts zählt?

Gruß
micha
OP Persönliche Seite #978273
Lesenswert?

> schon mal
>
1
>     RB1 ^= 1;
2
>
> benutzt, um den Portpin zu toggeln?

Werde ich morgen mal versuchen. Was genau macht denn "^" ?

> 1/ Oszilloskop richtig kalibriert, Timebase richtig eingestellt und
> korrekt abgelesen?

auf jeden Fall ;-)

> 2/ Mit welchem Takt läuft der PIC? Reicht die Rechenleistung bei dieser
> Taktrate für 125 kHz aus? Das Aufrufen der Interruptroutine und die
> Abarbeitung benötigt Rechenzeit.
>
> Die maximal mögliche Togglefequenz bei gegebener Taktrate könntest du
> herausfinden, indem du den Timer mal weglässt und die Hauptschleife so
> machst:
>
1
>     while (1) 
2
>     {
3
>       RB1 ^= 1;
4
>     }
5
>

Das werde ich mal versuchen.
Die Rechenleistung sollte durchaus reichen. Der PIC läuft auf 4 MHz.

> 3/ Stimmt der Prescaler und der Vorladewert von TMR0?
>
> TMR0 = 255 heisst ja, dass der nächste Timertakt bereits den
> Overflow-Interrupt auslöst. Im Interrupt kommt dann der Reset auf 255.
> D.h. du arbeitest zusammen mit dem Prescaler im schnellstmöglichen
> Interruptbetrieb! Ich schätze Punkt 2/ kneift dich.

Das ist gewollt. Deshalb habe ich auch einen Vorteiler von 1:8 
eingestellt.

Da der Timer ja auf 1/4 der PIC-Frequenz arbeitet heißt das, dass die 
Timerfrequenz 1MHz beträgt und damit nach 1/8 von 1 MHz also 125 KHz der 
Interrupt ausgelöst wird.


> Viele (alle?) PICs nutzen als Zählertakt nicht die Quarzfrequenz,
> sondern nur ein Viertel davon.
> Mach doch mal  genauere Angaben bzgl. Quarztakt.

Quarz: 4MHz.
Daher ist die Timerfrequenz 1/4 4MHz = 1 MHz.

> Das liegt an deinem Code.
> Für den Low-Bereich wird nur "if RB1 == 0" abgearbeitet; für High "if
> RB1 == 0" und "if RB1 == 1".
>
> Das kannst du aber so lösen indem du schreibst
> RB1 = ~RB1;

Danke, werd ich gleich mal versuchen.
Was macht denn "~" genau?

> Bist du sicher, dass dein Timer rückwärts zählt?

Nö warum sollte er. Ich habe ja den Vorteiler auf 1:8 gestellt und damit 
sollte der Timer alle 0,000008 Sek (8µs) den TMR0 incrementieren und 
somit, da TMR0 auf 255 vorgeladen wird, den Interrupt auslösen.


Danke & Gruß,
 Tobias
Gast #978341
Lesenswert?

>Da der Timer ja auf 1/4 der PIC-Frequenz arbeitet heißt das, dass die
>Timerfrequenz 1MHz beträgt und damit nach 1/8 von 1 MHz also 125 KHz der
>Interrupt ausgelöst wird.

Und der PIC läuft auch nur mit 1MHz. Also 1us pro Befehl.
D.h. du hast 8 Befehle um irgendwas mit 125kHz auszugeben.
Einige Befehle brauchen aber auch mehr als 1us.
Wie bitte schön soll das jemals funktionieren ?
OP Persönliche Seite #979031
Lesenswert?

Ich glaube du hast da was falsch verstanden.
Der Pic läuft auf 4 MHz.
Wie kommst du darauf, dass der Pic nur auf 1 MHz läuft?

Der Timer läuft mit 1/4 des Pic-Taktes. D.h. aber nicht, dass der Pic 
auch auf 1 MHz läuft. Der läuft weiterhin auf 4 MHz.

Somit braucht ein Zyklus 25ns.
Wo ist dann das Problem? 125 KHz entsprechen einer Periode von 8µs.
Somit habe ich 32 Zyklen Zeit für andere Geschichten.

Oder verstehe ich da etwas falsch?
#979414
Lesenswert?

Tobias John wrote:
> Werde ich morgen mal versuchen. Was genau macht denn "^" ?
^ ist das Exklusiv-Oder ... wird vermutlich nicht unbedingt zu dem 
gewünschten Ergebnis führen.

>> Das kannst du aber so lösen indem du schreibst
>> RB1 = ~RB1;
> Danke, werd ich gleich mal versuchen.
> Was macht denn "~" genau?

~ ist eine einfache Negation (Einer-Komplement).

>> Bist du sicher, dass dein Timer rückwärts zählt?
> Nö warum sollte er. Ich habe ja den Vorteiler auf 1:8 gestellt und damit
> sollte der Timer alle 0,000008 Sek (8µs) den TMR0 incrementieren und
> somit, da TMR0 auf 255 vorgeladen wird, den Interrupt auslösen.

Gut okay, wenns gewollt war ists okay.

Was soll denn eig. für Signal rauskommen?
Soll eine komplette Schwingung 125kHz sein oder nur der Umschwung von 
high-low/low-high? Das ist ein Unterschied. Sonst bräuchtest du ja eine 
Timerfrequenz von 250kHz.

Versuch mal, dass Rücksetzen des Timers (auf 0xFF) gleich ganz am Anfang 
der Interruptroutine zu machen.

Gruß
micha
OP Persönliche Seite #979703
Lesenswert?

> Somit braucht ein Zyklus 25ns.
sorry, ich meine 250ns

>Was soll denn eig. für Signal rauskommen?
>Soll eine komplette Schwingung 125kHz sein oder nur der Umschwung von
>high-low/low-high? Das ist ein Unterschied. Sonst bräuchtest du ja eine
>Timerfrequenz von 250kHz.

Es soll eine komplette Periode mit T=8µs bei rauskommen. D.h. der 
high-bereich soll 4µs und der low-bereich soll 4µs sein.
Aber Dein Hinweis ist glaube ich nicht ganz falsch. Da muss der 
Interrupt natürlich mit einer Frequenz von 250kHz auslösen.

Ich probiere das gleich mal aus.

Danke!
Gast #979756
Lesenswert?

Passt vielleicht nich ganz zum Thema, aber trotzdem: Für welche 
Operation, Negation oder Exclusives-Oder, werden eigentlich mehr Takte 
benötigt?

Noch was: Das Abarbeiten des Interrupts benötigt doch auch in 
irgendeiner Weise Rechenzeit bzw. eine bestimmte Anzahl an Takten. 
Müsste man dann nicht einen anderen Vorteiler nehmen (eine größere 
Auflösung) und das Abarbeiten, des Interrupts auch in den Startwert des 
Timers mit einbeziehen? (Genau meine ich den ersten Befehl des 
Interrupts - Timer resetten.)

Für das Problem hier ist das vermutlich irrelevant, da hier ein paar Hz 
mehr oder weniger wohl egal sind.


Gruß

Michael

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren