Forum: Compiler & IDEs MSP430 Timer abschalten


von Sebastian S. (harryporter1980)


Lesenswert?

Hallo,

hab ein kleines Problem, stecke noch nicht so in der Materie:

Arbeite mit dem MSP430. Und wenn ich das richtig verstanden habe, läuft 
ein Timer immer und ewig, nachdem man ihn initialisiert hat, oder? Ich 
möchte nun aber, dass dieser Timer nur 1x hochläuft. Wie kann ich den 
Timer wieder auf 0 setzen oder ganz deinitialisieren?

Wäre schön, wenn jemand was weiß.

Gruß
Der Anfänger...

von würschtl (Gast)


Lesenswert?

TACTL = 0;

von Sebastian S. (harryporter1980)


Lesenswert?

Für Timer B entsprechend TBCTL = 0. Oder?

von Sebastian S. (harryporter1980)


Lesenswert?

Leider klappt es mit dem Zurücksetzen nicht so richtig. Muss wohl mein 
Problem genauer darstellen:

In meinem Programm wird eine Funktion durch einen Interrupt am Port2 
aufgerufen. In dieser Funktion wird ein Timer inintialisiert und der 
Port3 auf 1 gesetzt. Nach einer gewissen Zeit soll dieser Port wieder 
auf 0 gesetzt werden. Dies soll aber nur 1x passieren. Deshalb soll der 
Timer zurückgesetzt werden.

Nur zur Info: in der Zwischenzeit erreichen weitere Interrupts den 
Port2.

Die Initialisierung meines Timers in der aufgerufenen Funktion 
"Funktion" sieht so aus:

void Funktion(void)
{
TBCTL = TBSSEL1 + TBCLR;
TBCCTL0 = CCIE;
TBCCR0 = 10000;
TBCTL |= TBSSEL_2 + MC_2 + TBIE;
_BIS_SR(LPM0_bits + GIE);

P3OUT = 0x01;                           //Port auf 1 setzen
}

Der Interrupt, in dem der Timer und der Port zurückgesetzt werden 
sollen, sieht so aus:

__interrupt void TIMER_B(void)
{
P3OUT = 0x00;
TBCTL = 0;
}

Hab das Gefühl, das der Controller in Zeile, in der der Port3 auf 1 
gesetzt wird, hängen bleibt.

Hätte jmd 'ne Idee?

von Stefan (Gast)


Lesenswert?

>Hab das Gefühl, das der Controller in Zeile, in der der Port3 auf 1
>gesetzt wird, hängen bleibt.
Was soll er denn sonst machen? Du schickst ihn ja schlafen:
1
_BIS_SR(LPM0_bits + GIE);

Vermutlich kommen Deine Port2-IRQ's noch bevor TimerB ablaufen kann 
(also 10000 erreicht). Dann erweckt der P2-IRQ Deinen MSP wieder kurz zu 
leben, springt in "Funktion" und setzt P3OUT = 0x01 !

Sieht auch verdammt nach rekursiven Funktionsaufrufen aus, denn der 
P2-IRQ springt ja wieder und wieder in "Funktion"...

von Sebastian S. (harryporter1980)


Lesenswert?

Was genau macht der Befehl

_BIS_SR(LPM0_bits + GIE);

denn eigentlich? Ich hab die Befehle von der TI-Seite. Leider steht da 
selten wofür die einzelnen Befehle sind. Soll ich den Befehl denn ganz 
weglassen?

Wie sollte ich das ganze denn anders aufbauen? Du hast recht, der P2-IRQ 
kommt in der Zeit, wo der Timer abläuft. Stellt das ein Problem dar?

von Falk B. (falk)


Lesenswert?

@ Sebastian S. (harryporter1980)

>Was genau macht der Befehl

>_BIS_SR(LPM0_bits + GIE);

>denn eigentlich? Ich hab die Befehle von der TI-Seite. Leider steht da

Die Frage kommt ein wenig spät ;-)

>selten wofür die einzelnen Befehle sind. Soll ich den Befehl denn ganz
>weglassen?

Kommt drauf an was du machen willst. Der Befehl schaltet die Interrupts 
global ein (GIE) und versetzt die CPU in den LPM0, Low Power Mode 0. 
Dabei wird die CPU angehalten. Sie wacht nur auf wenn ein Interrupt 
ausgelöst wird, führt den aus und legt sich am Ende des Interrupts 
wieder schlafen. Das Hauptprogramm bleibt dabei stehen.

MFG
Falk

von Stefan (Gast)


Lesenswert?

>Ich hab die Befehle von der TI-Seite. Leider steht da
>selten wofür die einzelnen Befehle sind.
Dafür gibt's ja die MSP-User-Guides bzw. die User-Guides der 
IAR-Entwicklungsumgebung, die dich darüber umfassend informieren.
Ich gebe zu, ist am Anfang etwas viel zu lesen... aber es ist noch kein 
Meister vom Himmel gefallen... da musst Du halt durch, wie alle anderen 
auch ;-)

>Soll ich den Befehl denn ganz weglassen?
S.oben! Durch planloses rumprobieren entsteht nur in den seltensten 
Fällen ein lauffähiges Programm!!!

Ohne nähere Informationen, was Dein Programm genau machen soll, ist 
weitere Hilfe unmöglich.

Nur ein genereller Hinweis:
1
_BIS_SR(LPM0_bits + GIE);
birgt gleich zwei Gefahren in sich:
1.) Den globalen IRQ (GIE) innerhalb einer ISR wieder frei zu geben, 
sollte man möglichst vermeiden. Führt oft zu unvorhersagbarem Verhalten!
2.) Den Sleep-Modus innerhalb einer ISR zu aktivieren ist nicht der 
richtige Weg! Die ISR kann nie beendet werden und jeder neue IRQ ruft 
eine "neue" ISR auf, die wiederum nicht beendet werden kann. D.h. früher 
oder später wird dir der Stack überlaufen.
Besser wäre es, in Deiner ISR lediglich Status-Flags zu setzen, und 
diese in Deinem main-Programm auszuwerten und dort den LPM zu setzen.
Oder Du verwendest zumindest
1
_BIS_SR_IRQ(LPM0_bits);
damit LPM0 erst aktiviert wird, nachdem die ISR abgearbeitet wurde!

>Wie sollte ich das ganze denn anders aufbauen? Du hast recht, der P2-IRQ
>kommt in der Zeit, wo der Timer abläuft. Stellt das ein Problem dar?
Offensichtlich schon, denn jeder P2-IRQ setzt Deinen Timer_B zurück, 
bevor dieser den gewünschten CCR0-IRQ aulösen kann!
Vielleicht solltest Du darüber nachdenken, den P2-IRQ nach dessen erstem 
Auftreten wieder zu sperren, damit er Dir nicht mehr in die Quere kommt. 
Nachdem Dein Timer dann gefeuert hat, kannst Du u.U. den P2-IRQ wieder 
zulassen, falls für Dein Programm notwendig ?!

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.