Hallo! Bei der Programmierung meines Controllers für die Ansteuerung von Thyristoren bin ich auf ein Problem mit meinem Timer gestoßen. Mein genutztes System: -MSP430FG4618 -32kHz Quarz für ACLK -IAR Embedded Workbench Version 5.10.1 -Programmierung in C Zur besseren Fehlersuche habe ich mein Programm möglichst weit gekürzt. Da ich quasi keine Erfahrung mit C habe und es sich um mein erstes Projekt mit einem Mikrocontroller handelt, hoffe ich das nicht zuviele grundsätzliche Fehler vorhanden sind. Was im Programm eigentlich passieren soll: An Pin 0 von Port 1 ist das Ausgangssignal eines Schmitt-Triggers angeschlossen, dieser liefert mir alle 20ms eine steigende Flanke. Der durch die Flanke ausgelöste Interrupt testet von welchem Pin der Interrupt kommt (später sollen 3 Schmitt-Trigger angeschlossen werden) und legt dann in den Variablen thyristorA1 und thyristorA2 ab welche Ausgangspins später auf High gesetzt werden sollen. Danach wird TimerA im up-mode gestartet. TACCR0 wird auf einen Wert in Abhängigkeit von alpha gesetzt. In dem Programm im Anhang ist alpha zwar konstant, im ungekürzten Programm wird es aber verändert.. Im Timer Interrupt werden dann die Pins an Port 4 entsprechend thyrsitorA1 auf High gesetzt und der Timer wieder gestartet, diesmal mit TACCR0 = alphaT[2]; was TACCR0 = 560 entsprechen sollte. Beim zweiten Timer Interrupt werden die Pins von Port 4 wieder auf Low gesetzt und der Timer mit einem größeren Überlaufwert TACCR0 = alphaT[10]; (TACCR0=2778) gestartet. Der dritte Timer Interrupt setzt die Pins entsprechend thyristorA2 auf High und startet den Timer mit TACCR0 = 560. Beim letzten Timer Interrupt werden die Pins wieder auf Low gesetzt und der Timer nicht wieder gestartet. Dieser Teil des Programms funktioniert soweit auch (falls man den Basic Timer nicht starten würde). Wenn jetzt zusätzlich noch der Basictimer genutzt wird, auch wenn er nur eine Varible hochzählt die mit dem Rest nichts zu tun hat, kommt es zu Problemen. Wenn ich mir das Signal der Ausgangspins auf dem Oszi anschaue, ist manchmal alles wie es sein soll, manchmal werden die Pins aber auch im falschen Moment auf High gesetzt. Die beiden Fälle in denen der Timer nur bis TACCR0 = alphaT[10] laufen soll sind in Ordnung, aber wenn der Timer Interrupt erst bei dem höheren Wert TACCR0 = alphaT[10] kommen sollte, wird direkt die ISR aufgerufen. D.h. die Phase zwischen den Zeitabschnitten in denen die Pins auf High liegen ist fast nicht mehr vorhanden. Ich glaube ich habe irgendetwas grundsätzliches bei der Nutzung von mehreren Interruptquellen falsch gemacht und wäre froh über jeden Tipp! Im Moment sind alle Variablen als volatile deklariert, wobei ich eigentlich dachte es wäre nicht bei allen nötig...dadurch tritt der Fehler aber seltener auf. Wenn ich das Programm Schritt für Schritt debugge funktiert es wie es soll. Soweit ich den Assembler Code (habe so gut wie garkeine Ahnung von Assembler) nachvollziehen kann, konnte ich auch keinen Fehler finden.... Danke schonmal für alle Antworten! Gruß
Hallo nochmal! Ich konnte den oben beschriebenen Fehler noch weiter einschränken, wenn ich in dem Programm im ersten Beitrag in: [c] #pragma vector = BASICTIMER_VECTOR __interrupt void BASICTIMER_ISR (void) { uint16_t bt = btcounter; if ( bt == 20 ) { bt = 0; } btcounter = ++bt; } [\c] die Variable "bt" ebenfalls als volatile deklariere tritt der Fehler nicht auf, oder zumindest so selten, dass ich ihn nach mehreren Minuten nicht mehr am Oszi beobachten konnte. Leider verstehe ich nicht warum es so ist, da der Fehler ja bei TimerA auftritt und nicht beim Basic Timer. Der Assembler Code den der Compiler ausspuckt unterscheidet sich dementsprechend auch nur minimal: Funktioniert nicht:
1 | BASICTIMER_ISR: |
2 | ?cstart_end: |
3 | 003128 120F push.w R15 |
4 | /*volatile*/ uint16_t bt = btcounter; |
5 | 00312A 421F 110C mov.w &btcounter,R15 |
6 | if ( bt == 20 ) |
7 | 00312E 903F 0014 cmp.w #0x14,R15 |
8 | 003132 2001 jne 0x3136 |
9 | bt = 0; |
10 | 003134 430F clr.w R15 |
11 | btcounter = ++bt; |
12 | 003136 531F inc.w R15 |
13 | 003138 4F82 110C mov.w R15,&btcounter |
14 | } |
15 | 00313C 413F pop.w R15 |
16 | 00313E 1300 reti |
17 | __interrupt void P1_ISR (void) |
18 | { |
Funktioniert:
1 | BASICTIMER_ISR: |
2 | ?cstart_end: |
3 | 003128 120F push.w R15 |
4 | 00312A 8321 decd.w SP |
5 | volatile uint16_t bt = btcounter; |
6 | 00312C 4291 110C 0000 mov.w &btcounter,0x0(SP) |
7 | if ( bt == 20 ) |
8 | 003132 90B1 0014 0000 cmp.w #0x14,0x0(SP) |
9 | 003138 2002 jne 0x313E |
10 | bt = 0; |
11 | 00313A 4381 0000 clr.w 0x0(SP) |
12 | btcounter = ++bt; |
13 | 00313E 412F mov.w @SP,R15 |
14 | 003140 531F inc.w R15 |
15 | 003142 4F81 0000 mov.w R15,0x0(SP) |
16 | 003146 4F82 110C mov.w R15,&btcounter |
17 | } |
18 | 00314A 5321 incd.w SP |
19 | 00314C 413F pop.w R15 |
20 | 00314E 1300 reti |
Kann mir jemand erklären wieso diese lokale Variable im Interrupt des Basictimers meinen TimerA beeinflussen kann? Gruß
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.