Forum: Mikrocontroller und Digitale Elektronik STM32 Timer Überläufe Zählen


von Skha (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, ich muss noch mal mit einer Timergeschichte nerven. Ich habe das 
Problem, dass ich einen Comparewert (CC1) habe, bei dessen Erreichen ein 
Wert an den CC2 übergeben wird und die Auslösung von CC2 freigegeben 
wird. Wird CC2 erreicht, wird über einen CC2-Interrupt eine Flanke 
ausgegeben. Der Wert von CC2 wird bei der Übergabe als neuer CC1 
vorgegeben. CC1 dient als Überlaufzähler (da die Werte viel größer sein 
können als der Timer fassen kann) (maximale Größe möchte ich ungern 
festlegen). Liegen der alte CC1 und der neue CC1 jetzt zu dicht 
aneinander habe ich das Problem, dass scheinbar die erste Auslösung 
übersprungen wird, da der Timer schon weiter gezaehlt hat bevor das neue 
CC1 vorgegeben wurde.

Ich habe mir also überlegt einfach abzufragen ob der neue CC1 knapp vor 
dem alten CC1 liegt (bei 16Bit Timer habe ich mich auf 25000 
festgelegt). Ist dies der fall wird das CC1 um 2^15 Bit weiter nach 
"rechts" verschoben (einfache Addition). Außerdem wird ein Überlauf 
abgezogen, da ja nun eine zusätzliche "Timerrunde" durchlaufen werden 
muss. Das Problem ist jetzt, dass es scheinbar so ist dass sobald das 
neue CC1 weit genug vom alten entfernt ist der Überlauf trotzdem gezählt 
wird. Man sieht auch deutlich, dass sobald die 25000 erreicht sind sich 
alles wieder normalisiert. Lässt man den beschriebenen Trick weg setzt 
eine Flanke aus sobald der neue CC1 etwas größer als der alte CC1 ist 
und hört nach einer gewisschen Distace wieder auf. Ich bin auch der 
Meinung die Flags alle richtig resetet zu haben. Momentan werden die 
Zeilen mehr als 100 mal pro Ausgabe durchlaufen. Zeitlich sollte es also 
keine Probleme geben.

1
        //Frequenzvorgabe neu laden
2
      if(Test_Verriegelung == RESET)        //erst wenn neuer Impuls freigegeben wurde und damit neuer Startwert festliegt
3
      {
4
        n_Tim4_Erweiterung_CC1 = (n_Frequenzvorgabe >> 16) + 1;  //Timererweiterung für CC1 "Überläufe"
5
6
        //Wenn CC1 gegenüber des realen CC1 vorgegeben wurde muss eine Undrehung abgezogen werden zum Ausgleich
7
        if(test_CC1 == 1)
8
        {
9
          n_Tim4_Erweiterung_CC1--;
10
          test_CC1 = 0;
11
          TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
12
        }
13
       Test_Verriegelung = SET;              //sperrt sich selbst bis neue Impulsauslösung stattgefunden hat
14
      }
15
      //32 Bit Erweiterung
16
      if(TIM_GetFlagStatus(TIM4, TIM_FLAG_CC1) == SET   &&     //Wenn Timer einmal durchgezählt hat (von CC1 bis CC1) "Überläufe"
17
         n_Tim4_Erweiterung_CC1 > 0                     &&     //Wenn noch nicht alle "Überläufe" durchgeführt
18
         Test_Verriegelung == SET              )    //Aufruf erst wenn neue Frequenz vorgegeben wurde (if darüber)
19
      {
20
        n_Tim4_Erweiterung_CC1 --;
21
        TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
22
      }
23
24
      //Freigabe für neue Flankenausgabe (Pause abgeschlossen)
25
      if(n_Tim4_Erweiterung_CC1 == 0                      &&  //Timererweiterung muss abgeschlossen sein
26
         Flag_pos_Flanke_ausgegeben == SET                &&   //letzte Flankenausgabe muss abgeschlossen sein bevor neuer Starimpuls vorgegeben wird
27
         Flag_neg_Flanke_ausgegeben == SET        )
28
29
      {
30
       Merker_High_Flanke = SET;                //Freigabe zur Auswertung neuer Flanken       n_Tim4_Erweiterung_CC1 --;
31
       n_Timer4_Ausgabe_Startwert_pos = (n_Timer4_Impulsstart + n_Frequenzvorgabe); //Übergabe des Startwertes für Auslösung neuer Flanken       
32
       Test_Verriegelung = RESET;                //Freigabe: neue Frequenz darf vorgegeben werden (1. if-Bedingung)
33
34
35
        //Wenn neuer Startwert zu dicht am alten liegt muss CC1 weiter nach hinten verlegt werden, damit es nicht übersprungen wird 
36
        //(Zum ausgleich wird in der ersten If-Bedingung ein CC1 Überlauf abgezogen)
37
        if((n_Timer4_Ausgabe_Startwert_pos > n_Timer4_Impulsstart && 
38
        (n_Timer4_Ausgabe_Startwert_pos - n_Timer4_Impulsstart) < 25000) || 
39
        (n_Timer4_Ausgabe_Startwert_pos < n_Timer4_Impulsstart && 
40
        (65535 - n_Timer4_Impulsstart + n_Timer4_Ausgabe_Startwert_pos) < 25000))
41
        {
42
          TIM_SetCompare1(TIM4, (n_Timer4_Ausgabe_Startwert_pos + 32767));  //setze comparewert 1 gegenüber des gerade ermittelten Ausgabestartwerts
43
          test_CC1 = 1;
44
          TIM_ClearFlag(TIM4, TIM_FLAG_CC1);
45
        }
46
        else
47
        {
48
          TIM_SetCompare1(TIM4, n_Timer4_Ausgabe_Startwert_pos);  //setze comparewert 1 auf gerade ermittelten Ausgabestartwert
49
        }
50
      }

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.