www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 Timer + Port Interrupt


Autor: bumpl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habe ein Problem mit den Timern beim MPS430F5438 und den Interrupts.
Folgendes: Ich starte einen Timer, der per Interrupt eine Zählvariable 
setzt.
Zusätzlich soll aber noch auf eine Lo/Hi-Fanke an Pin 1.4 reagiert 
werden.

Code ist hier:
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR |= 0x01;                            // P1.0 output
  TBCTL = TBSSEL_2 + MC_2 + TBCLR + TBIE;   // SMCLK, contmode, clear TBR
                                            // enable interrupt
  
  P1REN |= 0x10;                            // Enable P1.4 internal resistance
  P1OUT |= 0x10;                            // Set P1.4 as pull-Up resistance
  P1IE |= 0x10;                             // P1.4 interrupt enabled
  P1IES |= 0x00;                            // P1.4 Lo/Hi edge
  P1IFG &= ~0x10;                           // P1.4 IFG cleared

  //__bis_SR_register(LPM4_bits + GIE);       // Enter LPM4, enable interrupts
  __no_operation();                         // For debugger
}

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
 //mach was
}


#pragma vector=TIMERB1_VECTOR
__interrupt void TIMERB1_ISR(void)
{
  count++;
}

Das komische ist, dass beides jeweils einzeln funktioniert. Also, wenn 
ich den Timer nicht starte, oder einfach den Interrupt dafür nicht 
aktiviere (also TBIE weglasse), funktioniert der Interrupt auf Pin 1.4 
super.
Schalte ich allerdings den Timer-Interrupt ein, funktioniert dieser auch 
wunderbar, allerdings springt er mir nicht mehr in den Port-Interrupt.

Gitb's da irgendeinen Konflikt mit den Prioritäten? Oder sonst was?

Gruß,

bumpl

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solange die Interrupts nicht global eingeschaltet sind, wird nicht viel 
passieren.

Sie sind nicht eingeschaltet, weil
  //__bis_SR_register(LPM4_bits + GIE);       // Enter LPM4, enable 
interrupts

auskommentiert ist.

Es würde auch __bis_SR_register(GIE); ausreichen

Außerdem verlässt das Programm Main am Ende. Das darf nie passieren, 
sonst wird Code ausgeführt, der danach kommt, was zu irgendeinem 
beliebigen Verhalten führen kann.

Also sollte am Ende von Main ein for(;;); stehen oder irgend etwas 
anderes, das dafür sorgt, dass main nie verlassen wird.

Grüße,

Peter

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss man beim F5xxx nicht auch PxIFGx per Software zurücksetzen (wie 
beim F1xxx/2xxx) bzw. das PxIV Register auslesen um PxIFGx zu löschen?
Sonst springt er ja immer wieder in die Port-ISR!

Autor: Raimund (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh...
hab das Aktivieren der Interrupts Testweise mal auskommentiert, aber 
anders hats auch nicht funkioniert...

Main wird glaube ich nicht verlassen, weil ja beide Interrupts einzeln 
funktionieren. Außerdem habe ich das aus 2 Beispielen von TI 
zusammengebastelt, bei denen am Ende auch keine Englosschleißfe läuft.

>Muss man beim F5xxx nicht auch PxIFGx per Software zurücksetzen (wie
>beim F1xxx/2xxx) bzw. das PxIV Register auslesen um PxIFGx zu löschen?
>Sonst springt er ja immer wieder in die Port-ISR!

Das habe ich gemacht (dummerweise hier weggelassen). Wie gesagt: Die 
Interrupts einzeln genommen zeigen gewünschtes Verhalten. Zusammen 
allerdings springt er nie in die __interrupt void Port_1(void) Routine.

Gruß,

bumpl

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Zusammen allerdings springt er nie in die __interrupt void Port_1(void)
>Routine.
Und im PxIFG Register steht dann nix?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Also sollte am Ende von Main ein for(;;); stehen oder irgend etwas
>anderes, das dafür sorgt, dass main nie verlassen wird.
Das wäre sicher ein "sauberer" Programmierstil ;-)
Das ganze sieht aber nach IAR aus... der macht das automatisch!

>P1DIR |= 0x01;       // P1.0 output
Wäre ein Input nicht sinnvoller?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>P1DIR |= 0x01;       // P1.0 output
>Wäre ein Input nicht sinnvoller?
Vergiß es... hab mich verguckt.

Autor: bumpl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

im Register P1IFG ist P1IFG4 (für den Port 1.4) immer 0.

In dieser Konfiguration funktioniert der Interrupt auf Port 1.4 
hervorragend:
void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  P1DIR |= 0x01;                            // Set P1.0 to output direction
  P1REN |= 0x10;                            // Enable P1.4 internal resistance
  P1OUT |= 0x10;                            // Set P1.4 as pull-Up resistance
  P1IE |= 0x10;                             // P1.4 interrupt enabled
  P1IES |= 0x10;                            // P1.4 Hi/Lo edge
  P1IFG &= ~0x10;                           // P1.4 IFG cleared

//  TBCTL = TBSSEL_2 + MC_2 + TBCLR + TBIE;   // SMCLK, contmode, clear TBR

  __bis_SR_register(LPM4_bits + GIE);       // Enter LPM4 w/interrupt
  __no_operation();                         // For debugger
}

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
  P1OUT ^= 0x01;                            // P1.0 = toggle
  P1IFG &= ~0x010;                          // P1.4 IFG cleared
}

Kommentier ich TBCTL wieder ein (sagt man das so? :)), dann geht der 
Interrupt wieder nicht. Starte ich den Timer mit
TBCTL = TBSSEL_2 + MC_2 + TBCLR;
geht auch der Interrupt auf Port 1.4 wie vorher ohne Probleme.

Es liegt also wohl an dem Aktivieren des Interrupts für den Timer (bei 
Timer1/A übrigens das gleiche Problem).

Gruß,

bumpl

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kontaktier mal den TI support.
Wäre ja nicht das erste Mal, dass die Errata nachgebessert werden muss.
Hab die Jungs auch schon ein paar mal in Erklärungsnot gebracht ;-)

Autor: Raimund (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

tut mir leid, dass ich da nicht früher drauf gekommen bin und das Thema 
hier aufgebracht habe.
Die Lösung ist ziemlich naheliegend. Der Timer läuft mit einem Quarz auf 
32768 Hz. Die Priorität des Timers ist die höchste (15). Der Port 
Interrupt wird einfach nie ausgeführt, weil immer der Timer-Interrupt 
früher dran ist. Ich habe den Timer-Interrupt auf ca. 6,67 Hz gesetzt 
(mehr brauch ich) und jetzt geht auch der Port-Interrupt.

Gibt es denn eine Möglichkeit (vielleicht auch ASM), die Prioritäten der 
Interrupts zu ändern?

Gruß,

bumpl

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, die Interruptprioritäten sind fest vorgegeben.

Autor: S. Z. (szimmi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-Raimund schrieb:
> Hi,
>
> tut mir leid, dass ich da nicht früher drauf gekommen bin und das Thema
> hier aufgebracht habe.
> Die Lösung ist ziemlich naheliegend. Der Timer läuft mit einem Quarz auf
> 32768 Hz. Die Priorität des Timers ist die höchste (15). Der Port
> Interrupt wird einfach nie ausgeführt, weil immer der Timer-Interrupt
> früher dran ist. Ich habe den Timer-Interrupt auf ca. 6,67 Hz gesetzt
> (mehr brauch ich) und jetzt geht auch der Port-Interrupt.
>
> Gibt es denn eine Möglichkeit (vielleicht auch ASM), die Prioritäten der
> Interrupts zu ändern?
>
> Gruß,
>
> bumpl

Irgendetwas schleift hier trotzdem noch. In Deinem Ursprungsprogramm 
wird der Timer vom SMCLK, und dieser vom DCO (ca. 1MHz) getaktet. somit 
bekommst Du aller 65536 * 1us = 65,536 ms einen Timer-Interrupt. Wenn 
der P1-Interrupt nun deswegen nicht drankommt, weil der Timer ständig 
läuft, ist mir das schleierhaft, da die Timer-ISR dann schlappe 65ms 
etwas zu tun hätte...
Das Problem hat nichts mit Prioritäten zu tun. Kannst Du nochmal Dein 
vollstaendiges Programm posten, welches nun problemlos läuft?

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Irgendetwas schleift hier trotzdem noch. In Deinem Ursprungsprogramm
>wird der Timer vom SMCLK, und dieser vom DCO (ca. 1MHz) getaktet. somit
>bekommst Du aller 65536 * 1us = 65,536 ms einen Timer-Interrupt. Wenn
>der P1-Interrupt nun deswegen nicht drankommt, weil der Timer ständig
>läuft, ist mir das schleierhaft, da die Timer-ISR dann schlappe 65ms
>etwas zu tun hätte...
Richtig, ausserdem müsste das IFG Bit vom Pin ja trotzdem gesetzt 
werden.

Autor: Raimund Wagner (bumpl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

macht Sinn... Hier ist nun der Quellcode, der klappt:
#include "msp430x54x.h"

const F_A = 4915;

unsigned int count = 0;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR |= 0x01;                            // P1.0 output
  
  TA0CCTL0 = CCIE;                          // CCR0 interrupt enabled
  TA0CCR0 = F_A;
  TA0CTL = TASSEL_1 + MC_1 + TACLR;         // ACLK, upmode
  
  P1REN |= 0x10;                            // Enable P1.4 internal resistance
  P1OUT |= 0x10;                            // Set P1.4 as pull-Up resistance
  P1IE |= 0x10;                             // P1.4 interrupt enabled
  P1IES |= 0x00;                            // P1.4 Lo/Hi edge
  P1IFG &= ~0x10;                           // P1.4 IFG cleared

  __bis_SR_register(LPM3_bits + GIE);       // Enter LPM3, enable interrupts
  __no_operation();                         // For debugger
}

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
 //mach was

  P1IFG &= ~0x010;                          // P1.4 IFG cleared
}


#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER_A_ISR(void)
{
  count++;
  P1OUT ^= 0x01;
  TA1CCR0 += F_A;
  
}



Autor: S. Z. (szimmi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hiho,
also nochmal zu Deinem Urspungsprogramm.
Du sagtest, es hat entweder der eine oder der andere Interrupt 
zugeschlagen.
Den PORT1 Interrupt sehe ich ja noch ein, der andere (Timer) Interrupt 
kann gar nicht gekommen sein, da im LPM4 der SMCLK nicht läuft, somit 
auch der Timer steht.
Alles sehr seltsam. Dein letztes Programm sieht allerdings ganz gut aus, 
ACLK und LPM3, das passt.

Autor: bumpl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

hab's grad eben mit dem ersten Code noch mal versucht. Wenn der 
Timer-Interrupt aktiviert ist (... + TBIE), funktionert NUR der 
Timer-Interrupt. Entferne ich den Timer-Interrupt, dann funktioniert der 
Port-Interrupt (aber logischerweise nicht mehr der Timer-Interrupt).

Gruß,

bumpl

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.