Hallo,
ich arbeite mich gerade durch ein MSP430 Tutorial und bin im Abschnitt
timer interrupt service routines. Mein Programm hat einen Timer der bis
20000 zählt und dann einen Interrupt auslöst. In der Interrupt service
routine wird dann ein LED-Pin getoggelt. Das funktioniert auch in der
Anwendung, jedoch sehe ich in der Register-Übersicht beim Debuggen, dass
zwar der Interrupt ausgelöst wird sobald 20000 ausgelöst wird, aber das
TAIFG Bit nicht resettet wird. Es bleibt auf HIGH, obwohl in dem
Tutorial gesagt wurde, dass die ISR den interrupt cleart. Umsomehr
wundert mich, dass das Programm offenbar problemlos funktioniert. Im
Tutorial wurde darauf mit einem Satz eingegangen, was mir aber nichts
erklärt: However, it is also showing the TAIFG flag has gone HI. This is
just an artifact of how the ISR works with the MSP430FR6989 general
purpose timer.
Hat jemand eine Erklärung dafür? So etwas würde mich beim Debuggen
verwirren.
Mein Code:
1
#include<msp430.h>
2
3
#define RED_LED 0x0001 // P1.0 is the Red LED
4
#define STOP_WATCHDOG 0x5A80 // Stop the watchdog timer
5
#define ACLK 0x0100 // Timer ACLK source
6
#define UP 0x0010 // Timer Up mode
7
#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs
8
9
main()
10
{
11
WDTCTL=STOP_WATCHDOG;// Stop the watchdog timer
12
PM5CTL0=ENABLE_PINS;// Required to use inputs and outputs
Jonas W. schrieb:> Es bleibt auf HIGH, obwohl in dem> Tutorial gesagt wurde, dass die ISR den interrupt cleart.
Wobei ja der Pure Interrupt Aufruf das bit nicht löschen darf,
sonst kann ja nicht mehr geprüft werden was den Interrupt ausgelöst hat.
Das Interrupt Bit steht ja im direkten Zusammenhang mit dem TAIV
Sprungregister.
Ich habe mir angewöhnt aus Prinzip, nach abklären welchen Interrupt
ausgelöst wurde, den auch manuell zu löschen.
Da der Interruppt Einsprung mehrere Quellen hat, mache ich immer in der
Interrupt Rutine ein Sprung über das TAxIV Register
So ist auch sicher gestellt das wirklich der Timer die vorgegebene
Compare erreicht hat, und nicht ein anderer Interrupt dies ausgelöst
hat.
Hallo und danke für die Antwort,
Hier ist nochmal das Zitat aus dem Tutorial:
"In the past, we always had to make sure that we cleared the TAIFG flag
in the TA0CTL register after the timer elapsed. This is automatically
included by CCS with the TIMER0_A0_VECTOR ISR."
Also stimmt das ganz einfach nicht?
Dann nochmal eine andere Frage: Verstehe ich das richtig:
1) TAIFG zeigt an, dass für Timer_A ein Interrupt vorliegt.
2) Als nächstes muss ich das TAIV Bit im TA0IV Register auslesen um
herauszufinden, was für ein Interrupt vorliegt. Diese Überprüfung
geschieht auch in der ISR.
Und muss ich dann sowohl TAIFG und TAIV clearen sobald der Interrupt
verarbeitet wurde?
Mit freundlichen Grüßen,
J Witte
Hallo Jonas,
das entscheidende beim TimerA ist folgendes:
Two interrupt vectors are associated with the 16-bit Timer_A module:
• TACCR0 interrupt vector for TACCR0 CCIFG
• TAIV interrupt vector for all other CCIFG flags and TAIFG
Da der TA0CCR0-Interrupt exklusiv nur beim Erreichen des TA0CCR0-Wertes
gesetzt wird, wird dieser auch beim Einsprung in die ISR automatisch
gelöscht und man braucht da auch nicht nach Quellen unterscheiden, da es
nur eine Quelle gibt. Dein Code ist richtig.
Da Du TA0CCTL0 = CCIE; gesetzt hast, wäre das zu untersuchende Flag das
CCIFG in diesem Register. Ob man das Zurücksetzen beim Debuggen sieht,
weiß ich im Moment nicht, das hängt auch von den Einstellungen des
Debuggers ab, ob z.B. der Timeroszillator während des Single-steps
weiterläuft oder auch angehalten wird.
Das TAIFG im Register TA0CTL wird immer gesetzt, wenn irgendein
Timerinterrupt ausgelöst wird, hat aber keine Auswirkung, wenn nicht
gleichzeitig auch TA0IE gesetzt wurde, was in Deinem Code nicht der Fall
ist.
Gruß wv
Verstehe ich das richtig:
- Wenn ich TA0CCR0 verwende wird CCIFG automatisch gecleart.
- Wenn ich TA0CCR1 bis TA0CCR6 verwende muss ich das jeweilige CCIFG Bit
selber clearen.
- TAIV gibt an welcher Interrupt vorliegt. Es wird immer gesetzt außer
bei TA0CCR0.
- TAIV hat eine eigene ISR.
- TAIFG wird immer gesetzt, bei allen Interrupts.
- Wenn ich auch TAIE setzen würde, müsste ich bei jedem Interrupt
zusätzlich TAIFG clearen.
- Wenn ich TAIE nicht setze, führen zum Beispiel Timer Overflows nicht
zu einem Interrupt (wie in TAIV beschrieben).
VG Jonas
Hallo Jonas,
das ist so richtig.
Es gibt also nur zwei Interruptroutinen:
TIMER0_A0_VECTOR --> nur für CCR0
TIMER0_A1_VECTOR --> für alle anderen Capture/Compare Register und
Timer-Overflow
Gruß wv
TAIV ist das Register dass die Sprungadresse je nach Interrupt enthält.
Ist das Interrupt gelöscht enthält TAIV 0000h.
Und es steht ja dass man es Manuell löschen muss, wenn man nicht die
Standard Library verwendet:
Jonas W. schrieb:> "In the past, we always had to make sure that we cleared the TAIFG flag> in the TA0CTL register after the timer elapsed.
Was bedeutet dass man sicher sein soll dass es Zurückgesetzt ist.
Ansonsten kann bei einem anderem Interrupt nicht mehr festgestellt
werden, wer den Interrupt ausgelöst hat weil mehr als 1 Bit gesetzt ist.
> This is automatically> included by CCS with the TIMER0_A0_VECTOR ISR."
Was bedeutet dass wenn mann das CCS TIMER0_A0_VECTOR ISR library
verwendet dieses das Bit löscht. (Also nicht die CPU direkt, sondern das
Library enthält ein [BIC.W #TAIFG,&TAxCTL] befehl).
Dieser wird vom Compiler in die ISR gesetzt und der Debugger sieht das
löschen erst nach dem dieser Befehl ausgeführt wird.
Deshalb ist es noch gesetzt wenn du den Halt Befehl im Debugger setzt
oder per Single-stepp ausführst.
Würde das Bit nicht gelöscht, könnte dieser Interrupt nicht richtig
Identifiziert bzw ausgeführt werden.