-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 20

Thema: Timer und PWM

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.03.2005
    Ort
    Spanien
    Alter
    33
    Beiträge
    398

    Timer und PWM

    Anzeige

    Hallo.

    Ich wollte jetzt als nächstes einen Timer für meinen PIC16F876 @ 10MHz machen um ein PWM Signal zu erzeugen um dann zwei Servos anzuschliessen.
    Ich programiere in C und würde den Timer0 nehmen, der laut Sprut ein 8-Bit Timer ist und von 0 bis 255 zählen kann.

    Im Internet habe ich verschiedene Code Fragmente oder Formeln gefunden, weiss aber nicht ob und wie ich sie verwenden kann.

    Das erste wäre:

    time = 1/frequenz * 4 * Timerwert * vorteiler

    Jetzt habe ich aber auf einer anderen Seite diesen Code gefunden:

    Code:
    // Für Taktfrequenz des PIC = 4 MHz
    
    void Delay1ms( uns16 ms)                 //verstehe nicht warum "16ms". Ist nur ein Name,
                                             //da kann ich schreiben was ich will, oder?
    
    {
    while(ms)			// Schleife verlassen wenn ms=0 ist
    	{
        OPTION = 2; 		// Vorteiler auf 8 einstellen
                                       OK, die Tabelle mit den Vorteilern habe ich
                                       im Datenblatt auf Seite 47-48 vom PIC gefunden und bis da hin 
                                       vertehe ich es auch.
    
    
        TMR0 = 131; 		// 125 * 8 = 1000 (= 1 ms)
        while (TMR0);		// abwarten einer Milisekunde
        ms--;				// "ms" mit jeder Milisekunde erniedrigen
        }
    }

    Wenn ich die Formel von oben benutze um TMR0 auszurechnen kommt bei mir was anderes raus:
    1/4M * 4 * 125 *8 = 1ms TMR= ist also 125 und nicht 131
    Der Unterschied ist vieleicht nicht wichtig, aber ich verstehe nicht wie man auf 131 kommt.

    Nächster Code:

    Code:
    //Für Taktfrequenz des PIC = 20 MHz
    //Timerauflösung=13us
    //1ms/13us=77
    //delay<=255 !!
    //Nicht sonderlich genau !!
    void Delay1ms( uns16 time)
    {
       char next = 0;
        OPTION = 6; // prescaler divide TMR0 rate by 128
        TMR0 = 0;  //
        do  {
            next += 39;	// 4992=128*39 ,4992+15=5007/5=1,0014ms
            clrwdt();  // needed only if watchdog is enabled
            while (TMR0 != next)   // 125 * 8 = 1000 (= 1 ms)
        ;
        } while ( -- time != 0);
    }

    Laut Formel:
    1/20MHz *4 * 39 * 128 = 1ms Hm... OK, dann stimmt die Formel ja.

    Wenn ich bei meinem PIC jetzt einen 10MHz Quarz benutze, gilt dann für mich:

    1/10MHz * 4 * 20 *128 = 1ms ?

    Falls das so stimmt, könnte der timer in C dann so sein?
    Wie ihr seht habe ich den Code von oben genommen und verändert.

    Code:
    {
    void Delay_1ms( uns16 ms)  
    while(ms)
        {
          OPTION = 6;
          TMR0=20;
          while (TMR0);
          ms--;
          }
    }

    Muss ich sonnst noch etwas in den Code schreiben oder könnte ich das so in den PIC brennen?

    Wenn das funktioniert, habe ich dann noch eine Frage zum PWM zur Servo Steuerung, aber das später.

    Viele GrÜsse,
    Tornado

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.10.2004
    Ort
    ferd. Waldmüllerg. 7/2
    Alter
    32
    Beiträge
    456
    Also, zu "uns16 ms". Das ist einfach eine unsigned (also ohne vorzeichen) Variable vom Typ Integer (von 0 bis 65535) mit dem Namen ms. Die Funktion lässt dein PIC die durch diese Zahl angegebenen Millisekunden schlafen.

    1/4M * 4 * 125 *8 = 1ms TMR= ist also 125 und nicht 131
    Nein, vorsicht, die 125 sind die Schritte die der Timer zählen muss, bis er überfläuft. Also muss er am Anfang auf den Wert 256-125=131 gesetzt werden, damit er 125 Schritt bis zu einem Überlauf braucht.

    Und nein, dein Code geht wieder um einiges zu langsam, den du hast dir die Anzahl der Schritte errechnet. Der Startwert des Timers würde dann 256-20=236 sein.
    MfG
    Mobius

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.03.2005
    Ort
    Spanien
    Alter
    33
    Beiträge
    398
    Achso. Dann ist "Timerwert" also der Anfangswert um ab da x Schritte zu zählen (in meinem Fall 20).

    Wenn ich dich richtig verstehe müsste das dann so aussehen:
    1/10MHz * 4 * 236 *128 aber da kommen ja 12ms raus.

    Dann halt so:
    1000/128=7.8 also 8
    256-8=248
    1/10MHz * 4 * 248 * 128 = 12m Hmm.. das selbe wie eben. Ändern sich nur Zahlen hinter dem Komma.

    Dann verstehe ich das doch nicht. Ich wollte doch 1ms und nicht 12ms.
    Was mache ich falsch und wie mache ich es richtig?
    Grüsse,
    Tornado

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.12.2005
    Ort
    Euskirchen-Großbüllesheim
    Alter
    67
    Beiträge
    2.063
    Ein Timer setzt immer dann sein (Interrupt-) Flag, wenn ein Überlauf von 255 nach 256 = 0 stattfindet (256 gibt es bei 8 Bit ja nicht).
    Der Quarz hat eine Frequenz-Angabe, die in Zeit umgewandelt werden muß; das hast Du mit 1 / 1MHz schon gemacht; das ergibt 1 µs ! oder 0,001 ms !
    Wenn Du als Beispiel einen Teiler 1 : 4 wählst, mit dem Du dann auf 0,004ms kommst, dann muß ein Zähler 250 mal diese 0,004ms zählen, damit sich 1ms ergibt (0,004 * 250 = 1). Genau das macht das Timer-Register. Du legst mit dem Teiler eine 'Schritt-Zeit' für den Timer fest und setzt im Timer die Anzahl der Schritte.
    Allerdings wird dort nicht 250 eingesetzt, weil der Timer nicht runter zählt; er zählt rauf. Dann wäre der oben beschriebene Überlauf nach 6 Schritten (250 ... 256 = 6. Also mußt Du in den Timer die Zahl 6 reinschreiben (256 - 250 = 6), dann macht er genau 250 Schritte bis zum Überlauf bei 256, was 1ms entspricht.
    Den Timer-Wert mußt Du dann wieder neu eintragen, sofern es nicht ein Reload-Register dafür gibt.

    Edit: Hat noch keiner bemerkt, daß 10MHz keine 0,1µs = 0,001ms sind ?
    Dann korrigiere ich mal den Quarz von 10MHz auf 1MHz (dann brauche ich nur den µs-Wert ändern).
    MfG Karl-Heinz
    HobbyElektronik hier klicken ....

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.03.2005
    Ort
    Spanien
    Alter
    33
    Beiträge
    398
    Ich habe mir eure Antworten noch mal gründlich durchgelesen.
    Ich hoffe, dass ich es jetzt kapiert habe. Mal sehen...

    Für meine 10MHz müsste ja das hier gelten:
    1/10M= 0,0000001

    0.0000001 = 0.0001m

    0.0001m * 128(Vorteiler) = 0.0128m

    0.0128m*78=1m Ich brauche 78 Schritte a 0.0128m um auf 1m zu kommen

    256-78= 178 Dann muss ich ab 178 zählen.

    Code:
    {
    void Delay_1ms(uns16 ms)
    while(ms)
        {
        OPTION=6;   // Vorteiler auf 128
        TMRO=178;    // auf 178 um 78 Schritte zu zählen
        while (TMR0);
        ms--;
        }
    }
    Ist das so richtig?

    Was ist denn dann mit der "4" aus dieser Formel?
    time = 1/frequenz * 4 * Timerwert * Vorteiler

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.12.2005
    Ort
    Euskirchen-Großbüllesheim
    Alter
    67
    Beiträge
    2.063
    Auha, jetzt gibt es ein Problem; ich bin von Assembler ausgegangen (siehe Beispiele hier und hier ).
    Was bei C gemacht werden muß und was dort schon berücksichtigt wird, kann ich Dir leider nicht sagen. Ich mag kein C und kenne deshalb auch nicht die Bedeutung Deines Listings, zumindest nicht alles.
    MfG Karl-Heinz
    HobbyElektronik hier klicken ....

  7. #7
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    66
    Beiträge
    10.970
    Hallo tornado!

    Ich kenne C nicht und schreibe meine Programme für PIC´s nur im ASM.

    Deswegen versuche das mit einem 16-bitigen Timer kurz und programmiersprachlos zu erklären.

    Die Frequenz, die ein Timer zählt Fp ist gleich der Taktfrequenz F (Quarzt, oder änliches) geteilt durch Preskalerwert P (1,2,4,... u.s.w.), also Fp = F / P.

    Die impulsenzahl, nach der er ein interrupt durch gesetztes interrupt flag signaliesiert beträgt (FFFF h + 1) - (TMRXH, TMRXL), das heisst 10000 h - Timerwert, wobei der Timerwert ist eine 16-bitige Hexzahl die in die Timerregister TMRXH und TMRXL vor dessen Start eingeschriben wird.

    Die Zeit die vom Start des Timers bis zum von ihm ausgelösten interrupt vergeht beträgt T = 1/Fp * (10000 h - Timerwert).

    MfG

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    14.05.2005
    Ort
    Wallis
    Beiträge
    137
    Was ist denn dann mit der "4" aus dieser Formel?
    Die interne Frequenz des PIC ist gleich der Frequenz des Quarz dividiert durch 4.
    So stimmen auch deine Berechnungen nicht:

    time = 1/f(quarz) * 4 * Presc * Zählwert
    1ms = 1/10MHz * 4 * 16 * 156

    ==> Prescaler = 16
    ==> Zählwert = 156 (Einstellen musst du 256-156 = 100)

    Jedes mal wenn das Interrupt ausgeführt wird, wird die Interruptfunktion ausgeführt.

    Die Syntax würde in etwa so aussehen:
    Code:
    #INT_TIMER0
    deine_funktion() {
       ; deine Befehle
    }

  9. #9
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    66
    Beiträge
    10.970
    Hallo Benji!

    Du hast recht, der Systemtakt ist nicht gleich der Quarzfrequenz.

    Bei meinem Beitrag muss man also als F=Fq/4 nehmen, wo Fq Quartzfrequenz ist.

    Vielen Dank !

    MfG

  10. #10
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.03.2005
    Ort
    Spanien
    Alter
    33
    Beiträge
    398
    Mittlerweile bin ich etwas durcheinander.
    Ich werde mir morgen alles noch mal ganz in ruhe durchlesen.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •