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 | }
|