Hallo zusammen, wir sind gerade dabei, uns in den 16FX / MB96340 von Fujitsu einzuarbeiten und auch gleich eine Frage. - Der Prozessor läuft bei 16MHz. - Wir haben einen Reload-Timer (RLT1), der auf 12,5 uSekunden gesetzt ist und einen Interrupt auslöst. - Gleichzeitig haben wir einen Free-Running-Timer, den wir zur Zeitmessung einsetzen (mit Überlauferkennung). - Als dritten haben wir noch einen weiteren Reload-Timer (RLT0), der ebenfalls einen Interrupt auslöst; RLT0 wird nur für UART-Ausgaben benutzt und läuft alle 100ms. In dem Interrupt von RLT1 wird als erstes eine Zeitmessung vorgenommen (Zeit die seit dem letzen IRQ RLT1 verstrichen ist) - das Ergebnis wird gespeichert und dann in RLT0 ausgegeben. Soweit klappt´s ganz gut mit einigen kleinen Abweichungen bei der Zeitmessung. Ziel der Routine in RLT1 ist die generierung diverser PWM Signale mit vorheriger Ansteuerung von bis zu 7 Latches - diese Sachen sind im Moment noch NICHT implementiert. Es geht zunächst nur um ein Signal an PDR07_P0. Aber aus diesem Grund ist der Vergleich "L0_P0_Cnt" drin. Das zu erzeugende Signal ist im Moment auch egal (ebenfalls, dass es sicherlich einfachere Möglichkeiten gibt PPG, etc.). Meine Frage ist nun - wenn ich den mit "Block 1" (siehe unten) gekennzeichneten Block nicht drin habe, bekomme ich als Ergebnis 12,5 uSekunden für das Aufruf-Intervall RLT1. Sobald Block 1 drin ist, jedoch bereits 25 uSekunden. Verbrauchen so wenige Befehle aus "Block 1" (1 Division, 2 Vergleiche, 1-2 Variablen setzen, Variable erhöhen und Portausgabe) bereits mehr als 12,5 uSekunden, so dass ein Interrupt "verschluckt" wird ??? Habe die Main.c auch mal angehängt. Tut mir leid, es ist eher eine Grundsatzfrage - aber das sind die wichtigsten ;-) Ich kann mir nicht vorstellen, dass der uC so viel Zeit für so ein paar Befehle vernichtet !? Oder doch!? Danke, Sebastian --- __interrupt void RLT1_LatchTimer_IRQ (void) { // Zeitintervall seit letzem Aufruf FRT0_Count = TCDT0; FRT0_ovl1_cnt_func = FRT0_ovl1_cnt; // Save current FRT value Ticks=abs(FRT0_ovl1_cnt_func - FRT0_ovl1_cnt_old) * 0x10000UL + FRT0_Count - FRT0_Count_old; FRT0_ovl1_cnt_old = FRT0_ovl1_cnt_func; // Save current FRT value as reference for next cycle FRT0_Count_old = FRT0_Count; flag_ticks_valid=1; // ------------- BLOCK 1 START ------------- helper_RLT1 = 10000; // per Definition - "Teiler" 10 kHz if (L0_P0_Cnt>=(helper_RLT1 / L0_P0_Hz)) { // Zeit für einen Flankenwechsel // bestehender Wert kann nicht ausgelesen werden, sonst // würden wir den Wert aus dem letzten Latch bekommen! if (L0_Memory.bit.P00 == 1) { L0_Memory.bit.P00 = 0; } else { L0_Memory.bit.P00 = 1; } // Jetzt den Counter zurücksetzen // geht beides, 1. "sauberer" (kein Überspringen möglich) // 2. einfacher & schneller. // L0_P0_Cnt=L0_P0_Cnt-(helper_RLT1 / L0_P0_Hz); L0_P0_Cnt=0; } L0_P0_Cnt++; // Daten anlegen PDR07 = L0_Memory.byte; // ------------- BLOCK 1 ENDE ------------- TMCSR1_UF = 0; // reset underflow interrupt request flag return; }
Hallo nochmal, hat niemand eine Idee ode einen Tip dazu ? Oder habe ich das ganze zu umständlich geschildert ? Grüße, Sebastian
Hi, ich fürchte, die Long-Multiplikation verbraucht bereits viel Zeit. Du hast in deiner ISR rund 190 Zyklen bis zum nächsten IRQ Zeit. Bei einer Long-Multiplikation muß auf die interne Bibliothek zurückgegriffen werden, da die 16LX-CPU keine Instruktion dafür hat. Diese Funktion braucht rund 150 Zyklen. Kommt nun noch die Multiplikation im "Block 1" hinzu, war's das dann. 16 MHz sind halt nicht so ultra-flott. Gruß.
Hallo zusammen, ich habe mich heute nochmal an das Problem rangesetzt und versucht, das ganze zu lösen. Ist mir soweit auch gelungen, ich hätte nur ganz gerne Feedback, ob jemand in den Routinen noch Probleme und/oder Verbesserungsmöglichkeiten gibt. Ziel war, sowohl die 32bit Variable als auch die Multiplikation zu vermeiden:
1 | Ticks=abs(FRT0_ovl1_cnt_func - FRT0_ovl1_cnt_old) * 0x10000UL + |
2 | FRT0_Count - FRT0_Count_old; |
Ich habe folgendes gemacht (Kommentare habe ich zum besseren Verständnis drin gelassen):
1 | // Init:
|
2 | // timerOvl=4272, timerCnt=34480;
|
3 | // FRT0_ovl: aktueller Overflow Wert des Free-Running Timers
|
4 | // FRT0_cnt: aktueller Wert des Free-Running Timers
|
5 | // FRT0_ovl_old: vorheriger Overflow Wert des Free-Running Timers
|
6 | // FRT0_cnt_old: vorheriger Wert des Free-Running Timers
|
7 | |
8 | // Zunächst Differenzen ovl/cnt zu letztem Durchlauf bestimmen
|
9 | // und in diff_ovl und diff_cnt speichern.
|
10 | diff_ovl=FRT0_ovl-FRT0_ovl_old; |
11 | // folgt OF@Subtraktion bei diff_cnt?
|
12 | if (FRT0_cnt<FRT0_cnt_old) diff_ovl--; |
13 | diff_cnt=FRT0_cnt-FRT0_cnt_old; |
14 | |
15 | // Timer dezimieren
|
16 | // folgt OFSubtraktion bei @timerOvl?
|
17 | if (timerOvl<diff_ovl) { |
18 | // wenn ja, ist der Timer abgelaufen.
|
19 | timerOvl=diff_ovl; |
20 | }
|
21 | timerOvl-=diff_ovl; |
22 | // folgt OF@SubtraktionCNT?
|
23 | if (timerCnt<diff_cnt) { |
24 | if (timerOvl==0) { |
25 | timerCnt=diff_cnt; |
26 | } else { |
27 | timerOvl--; |
28 | }
|
29 | }
|
30 | timerCnt-=diff_cnt; |
31 | |
32 | if ((timerCnt==0) && (timerOvl==0)) { |
33 | Uart_SendString(0, "test-Counter expired.\n"); |
34 | // Reload values.
|
35 | // bereits "überschrittene" Zeit findet keine beachtung
|
36 | timerOvl=4272; timerCnt=34480; |
37 | }
|
38 | |
39 | FRT0_ovl_old = FRT0_ovl; |
40 | FRT0_cnt_old = FRT0_cnt; |
Gibt´s eine bessere Lösung und/oder Verbessungsvorschläge ? Danke, Sebastian
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.