mikrocontroller.net

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


Autor: Tobias John (tobiasjohn) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Unsymmetrisches Signal

Statt
    if(RB1 == 0)
      RB1 = 1;
    else if(RB1 == 1)
      RB1 = 0;

schon mal
    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:
    while (1)
    {
      RB1 ^= 1;
    }

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.

Autor: Der Micha (steinadler)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tobias John (tobiasjohn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> schon mal
>
>     RB1 ^= 1;
> 
> 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:
>
>     while (1) 
>     {
>       RB1 ^= 1;
>     }
> 

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

Autor: my name is nobody (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Very interesting Beitrag, aber
geht das auch in Assembler?

Autor: Tobias John (tobiasjohn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Tobias John (tobiasjohn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alle 8µs ein Wechsel wären 62,5 kHz.

Autor: Der Micha (steinadler)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tobias John (tobiasjohn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Tobias John (tobiasjohn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Der Micha (steinadler)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.