Forum: Mikrocontroller und Digitale Elektronik 125 KHz Rechtecksignal erzeugen mit PIC - erreiche nur 16KHz


von Tobias J. (tobiasjohn) Benutzerseite


Angehängte Dateien:

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

von Stefan B. (stefan) Benutzerseite


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.

von Der M. (steinadler)


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

von Tobias J. (tobiasjohn) Benutzerseite


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

von my name is nobody (Gast)


Lesenswert?

Very interesting Beitrag, aber
geht das auch in Assembler?

von Tobias J. (tobiasjohn) Benutzerseite


Lesenswert?

my name is nobody wrote:
> Very interesting Beitrag, aber
> geht das auch in Assembler?

Sicher geht das auch in Assembler.
Das Grundprinzip kann ich dir gerne erklären - aber mach doch dazu bitte 
ein neuen Beitrag auf, denn eigentlich soll hier das oben erläuterte 
Problem geklärt werden.

Gruß,
 Tobias

von holger (Gast)


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 ?

von Tobias J. (tobiasjohn) Benutzerseite


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?

von Ich (Gast)


Lesenswert?

Alle 8µs ein Wechsel wären 62,5 kHz.

von Der M. (steinadler)


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

von Tobias J. (tobiasjohn) Benutzerseite


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!

von Michael (Gast)


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

von Tobias J. (tobiasjohn) Benutzerseite


Lesenswert?

Genau, passt nicht ins Thema.
Und wie du siehst macht man mit solchen Beiträgen ein ganzes Thema mal 
eben "platt".

Danke!

I.ü. haut das mit dem Takterzeugen bei 4MHz wirklich nicht ganz hin.
Muss ich mal sehen ob ich nicht anders 125KHz erzeugen kann - ohne 
Mikrocontroller, was ja auch eigentlich unnötig ist ;-)

von Der M. (steinadler)


Lesenswert?

Du könntest höchstens nen größeren Controller nehmen und das ganze mit 
ner Hardware-PWM machen. Die stellst du einmal ein und dann musst du 
dich im Code nicht wieder drum kümmern.

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.