Forum: Mikrocontroller und Digitale Elektronik MSP430 - Timer Operation Wechsel?


von Semih A. (semih)


Angehängte Dateien:

Lesenswert?

Hallo,

hab folgendes Problem;
Ich möchte via Terminal 3 Zeichen einlesen. Das klappt dankt dem 
Beispiel aus der Code-Sammlung von TI (msp430g2xx1_ta_uart9600.c). In 
diesem Beispiel-Code wird ja der Timer für die UART-Übertragung benutzt.
Jetzt möchte ich aber, das nach Eingabe der 3 Zeichen via Terminal, die 
LED am Launchpad mit 1Hz (später wird die Frequenz von der Eingabe 
abhängen) blinkt. Funktioniert aber nicht.

Ich versuche:
1
TACCTL0 = CM0 + ~OUT + ~CCIE+  ~CCIFG + ~CAP + ~SCS + OUTMOD0 + ~CCIFG + ~COV;  // TACCTL0 zurücksetzen
2
TACCTL1 = CM0 + ~OUT + ~CCIE+  ~CCIFG + ~CAP + ~SCS + OUTMOD0 + ~CCIFG + ~COV;    // TACCTL1 zurücksetzen
3
CCTL0 = CCIE;                              // CCR0 interrupt enabled
4
CCR0 = 32768;                              // entspricht einer Sekunde
5
TACTL = TASSEL_1 + MC_1 ;                  // 32KHz Quarz , up mode
6
_BIS_SR(LPM0_bits + GIE);
Um die TACCTLx Interputs zu beenden, aber funktioniert nicht.

Hat da jemand Erfahrung mit?

von Jim M. (turboj)


Lesenswert?

Da fehlt das
1
while (1) {
2
 ;
3
}

am Ende von main(). Das Hauptprogramm will man nicht verlassen, dann 
macht der µC gerne mal Mist.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Semih Ali schrieb:
> TACCTL0 = CM0 + ~OUT + ~CCIE+  ~CCIFG + ~CAP + ~SCS + OUTMOD0 + ~CCIFG + ~COV; 
// TACCTL0 zurücksetzen

Das macht ganz sicher nicht das, was Du willst.

Sieh Dir beispielsweise den Wert von CCIE an; das ist Bit 4 und die 
Konstante CCIE hat folglich den Wert 0x10.

Was kommt dabei heraus, wenn Du das bitweise negierst?

Eben: 0xEF. Du willst aber einfach nur 0 erhalten, weil sonst Deine 
Registerinitialisierung was ganz anderes bewirkt.

Und so sieht das bei jedem anderen Bit auch aus, das Du versuchst auf 
diese Art und Weise zu löschen.

Lass die Bits weg, die Du auf Null setzen willst, und schreib das ganze 
so:

> TACCTL0 = CM0 + OUTMOD0;  // TACCTL0 zurücksetzen

von Semih A. (semih)


Lesenswert?

Vielen Dank für die Tipps.

Jim,
das mit dem while(1) braucht man glaube ich nicht immer (siehe 
msp430g2xx1_ta_01.c in den Beispielcodes von TI). Aber ich habe es mal 
sicherheitshalber reingesetzt.

Rufus,
danke für den Hinweis. Aber hat auch nicht geklappt.

Habe jetzt zusätzlich folgendes ausprobiert:

TACCTL0 = 0x0104;

Das entspricht dann nach dem Manual;
Bit 15-14 Capture mode:                     00 No capture
Bit 13-12 Capture/compare input select:     00 CCIxA
Bit 11    Synchronize capture source.:       0 Asynchronous capture
Bit 10    Synchronized capture/compare input 0
Bit 9     Unused                             0
Bit 8     Capture mode:                      1 Capture Mode
Bit 7-5   Outputmode                       000
Bit 4     Capture/compare interrupt enable.  0 Interupt disabled
Bit 3     Capture/compare input              0
Bit 2     Output                             1 Output low
Bit 1     Capture overflow                   0
Bit 0     Capture/compare interrupt flag     0

Funktioniert aber auch nicht. Wenn ich die ganze UART-Sachen weglassen, 
dann klappt das ja mit dem Blinken der LED...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Semih Ali schrieb:
> Habe jetzt zusätzlich folgendes ausprobiert:
>
> TACCTL0 = 0x0104;

Die Konstanten von TI solltest Du schon benutzen. Nur nicht mit Deinem 
fehlgeschlagenen Versuch, Nullen daraus zu machen.

Der würde funktionieren, wenn Du es so schriebest:
1
TACCTL0 = CM0 + (~OUT & OUT) + (~CCIE & CCIE) + (~CCIFG & CCIFG) + (~CAP & CAP) + (~SCS & SCS) + OUTMOD0 + (~CCIFG & CCIFG) + (~COV & COV);

aber daß das Blödsinn ist, muss ich wohl nicht erwähnen.

Also:
1
TACCTL0 = CM0 + OUTMOD0;

und gut ist.

Wenn der Kram dann immer noch nicht funktioniert, liegt die Fehlerquelle 
an einer anderen Stelle.

von Semih A. (semih)


Lesenswert?

1
TACCTL0 = CM0 + OUTMOD0;

habe ich ja auch ausprobiert. Funktioniert nicht.

Also UART funktioniert ja; Kann per Terminal die 3 Zeichen einlesen. Nur 
danach den Timer zu verwenden klappt nicht.
Wenn ich den ganzen UART kram weglasse, funktioniert das Blinken der LED 
mit dem Timer-Interrupt.

Was habe ich da übersehen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hmm. Du willst den gleichen Timer für die Software-UART und das Blinken 
verwenden; ist das sinnvoll?

Nach dem Empfang der drei Zeichen solltest Du, bevor Du den Timer 
umprogrammierst, die Interrupts erst mal wieder abschalten, dann den 
Timer komplett neu initialisieren und dann erst die Interrupts wieder 
einschalten.

Ist denn sichergestellt, daß Deine Empfangsroutine sich auch so verhält 
wie gewünscht, daß also Deine Timermanipulation auch wirklich erst nach 
Empfang der drei Zeichen ausgeführt wird?

Und willst Du auch wirklich, daß nach diesen drei empfangenen Zeichen 
nichts mehr empfangen werden kann?

von Semih (Gast)


Lesenswert?

Genau, also zunächst Timer für Uart und danach für das Blinken.
Ob, das sinvoll ist? Hmm, ich möchte später quasi per Terminal ggfs. 
Zahlenwerte (Intervallzeiten, Rundenanzahl...) die ich im Flash ablegen 
werde übers chreiben können. Mit einem 'Button'- Interrupt kann man die 
Zahlenwert Eingabe  überspringen bzw. Mit dem Blinkmodus erst starten.

Später soll das ein programmierbarer Intervall-Timer mit  Displayausgabe 
und Summer werden. Möchte gerne auf ein zusätzlichen Timer/RTC 
verzichten.

Werde deine Tipps mal ausprobieren. Vielen Dank!

von Holm T. (Gast)


Lesenswert?

Ich habe auch erstmalig auf einem MSP herumgehackt und eine Software 
UART
verwendet die den TimerA belegt.
Auf der Suche nach einer anderen Zeitbasis ist mir der mißbrauchbare 
Watchdog rechtzeitg über den Weg gelaufen, der macht nun alle 1,9ms 
einen Interrupt. Das sollte zum Blinken einer LED doch an Granularität 
dicke ausreichen?

Zähle einfach in einer ISR die Timerticks hoch..

Gruß,

Holm

von Semih A. (semih)


Lesenswert?

@Holm
danke für den Tipp. Aber ich hätte das Timing schon genauer; deshalb 
auch 32kHz Quarz. Oder kann man da auch den 32kHz auswählen?

@Rufus,

also irgendwie will das mit der Init. nicht funktionieren.
1
__bic_SR_register(LPM0_bits);  // Interrput ausschalten
2
mode = 1;                      //"Blink"-Modus
3
P1SEL = 0x00;                  // Timer Funktion für TXD/RXD pins zurücksetzen
4
TACCTL0 = CM0 +  OUTMOD0;  // TACCTL0 zurücksetzen
5
TACCTL1 = CM0 +  OUTMOD0;  // TACCTL1 zurücksetzen
6
CCR0 = 32768;      // entspricht einer Sekunde
7
TACTL = TASSEL_1 + MC_1         // 32KHz Quarz , up mode
8
CCTL0 = CCIE;                   // CCR0 interrupt enabled
9
_BIS_SR(LPM0_bits + GIE);       // Interrput einschalten

von Coder (Gast)


Lesenswert?

Und ne kleine Kleinigkeit:

Bitmasken sollte man mit einem | verknüpfen und nicht addieren. Ich habe 
die TI auch Beispiele und finde soetwas nicht so super. Sowohl das eine 
als auch das andere funktioniert natürlich.

von Coder (Gast)


Lesenswert?

PS:
Du kannst natürlich die Clock Source auswählen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Coder schrieb:
> Bitmasken sollte man mit einem | verknüpfen und nicht addieren.

Das ist korrekt; wobei ein bitweises OR und eine Addition auf das 
gleiche hinauslaufen, wenn man nicht versehentlich überlappende 
Bitwerte erwischt.

Insofern ist der von TI favorisierte Stil ein schlechter Stil, weil 
der bei solchen Fehlern recht gnadenlos ist.

Semih schrieb:
> Genau, also zunächst Timer für Uart und danach für das Blinken.

Und warum nicht einfach einen anderen Timer für das Blinken verwenden? 
Ist ja nicht so, daß Du von TI Geld zurückbekommst, wenn Du sowieso 
vorhandene Peripherie nicht verwendest ...

Und außerdem könntest Du die Blinkfrequenz auch mehrfach verstellen, 
ohne jedesmal einen Reset machen zu müssen.

(Noch einfacher würde die Angelegenheit werden, wenn Du einen MSP430 mit 
Hardware-UART verwendest, wie den 'F2253, der mittlerweile den 
Launchpads beiliegt, aber das ist wieder 'ne ganz andere Angelegenheit).

von Semih (Gast)


Lesenswert?

Also mein msp430g2231 hat laut Datenblatt nur ein Timer. Das mit dem 
Geld zurück habe ich nich verstanden.

Mit einem Timer bekommt man auch ein variable Blinkfrequenz ohne Reset 
hin. Ohne Software uart funktioniert das auch (einfach CCR0 verändern).

Werde demnächst mal die watchdog Variante ausprobieren.

von Semih A. (semih)


Lesenswert?

Okay, jetzt habe ich den Fehler gefunden:
1
P2OUT = 0x00;
2
P2SEL = 0x00;
3
P2DIR = 0xFF;

diese Zeilen musste ich entfernen. Ich habe nur ein G2231 und dieser hat 
kein P2...
Komisch das das in den Code-Beispielen so für G2231 drin steht...

Die Variante mit dem Watchdog funktioniert auch;

Vielen Dank nochmal an alle!

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.