Forum: Mikrocontroller und Digitale Elektronik MSP430 Interrupt Port1


von Mike (Gast)


Lesenswert?

Guten Morgen alle zusammen

Beim MSP430F149 sind ja die Ports 1+2 interruptfähig.
Ich frage mich nun, wie man mit einem Interruptvektor 2 verschiedene
Sachen ausführen kann. z.bsp. Soll bei Port1.0 bei der fallenden Flanke
etwas anderes passieren, als bei der steigenden Flanke an P1.7

Die Interruptroutine lautet ja bekanntlich folgendermassen:

#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{

   Anweisungen;
}

Muss man zusätzlich das P1IFG Flag mit der Software zurücksetzen oder
geschieht dies automatisch?

Gruss Mike

von Sebastian (Gast)


Lesenswert?

Dann prüf doch einfach hart die Ports ab:

#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{
  if (P1IN|0x01) tu_was_besonderes();  // 0x01 ist ja P1.0
  else if (P1IN|0x02) tu_was_anderes_tolles();  // 0x02 ist P1.1 usw.
}

von Mike (Gast)


Lesenswert?

soviel ich weiss, hat es ja für jeden port ein eigenes interruptflag

geht das so nicht:


#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{
if((P1IFG&0x01)==1)   //Wenn Flag von P1.0 gesetzt ist
    {
    LPM3_EXIT;
    lcd_initialisierung();
    }
if((P1IFG&0x80)==1)    //Wenn Flag von P1.7 gesetzt ist
    {
    P6OUT=0x00;
    P3OUT=0x00;
    LPM3;
    }
P1IFG=0;   //Inerruptflag zurücksetzen
}

von OldBug (Gast)


Lesenswert?

Wenn allerdings beide Möglichkeiten bestehen, dann kein else if, sondern
ein einfaches neues if:

#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{
  if (P1IN|0x01) tu_was_besonderes();      // 0x01 ist ja P1.0
  if (P1IN|0x02) tu_was_anderes_tolles();  // 0x02 ist P1.1 usw.
}

Geht auch mit switch-case:

  switch ((int)P1IN)
  {
    case 0x01:  /* P1.0 */
      break;

    case 0x02:  /* P1.1 */
    case 0x04:  /* P1.2 */
      break;

    case 0x03:  /* P1.0 && P1.1   */
    default:    /* unknown source */
      break;
  }

Gruß,
Patrick...

von OldBug (Gast)


Lesenswert?

Hups, hab Dein Posting übersehen!
Kannst natürlich auch die Flags anstelle der Ports abfragen!

Gruß,
Patrick...

von OldBug (Gast)


Lesenswert?

Oh, noch was: das "|" (fällt mir grad erst auf) muss ein "&" sein!

von Sebastian (Gast)


Lesenswert?

Ja, sehe ich genauso. Die Lösung mit den Flags ist sogar noch eleganter.
:-)

Und ob man das Flag zurücksetzen muss, steht 100%ig im User Guide.
Probier es doch einfach aus. Ich würde aber mal tippen, dass das
automatisch resettet wird (so wie z.B. beim USART-IR-Flag).

Grüße, Sebastian

von Mike (Gast)


Lesenswert?

muss man das P1IFG Flag wieder mit der Software zurücksetzen??

von Sebastian (Gast)


Lesenswert?

> Oh, noch was: das "|" (fällt mir grad erst auf) muss ein "&"
sein!

Mea culpa. Es ist noch so früh am morgen ... :-)

Grüße, Sebastian

von Sebastian (Gast)


Lesenswert?

> muss man das P1IFG Flag wieder mit der Software zurücksetzen??

AAAAAARGH! LIES! WAS! ICH! SCHREIBE!

Probier es doch einfach aus! Das dauert ca. 2 Minuten ... Debugger an,
IR-Flag in den Watch und los. Einmal mit resetten, einmal ohne. Dann
siehst du es doch. ;-)

von Ingo Henze (Gast)


Lesenswert?

Muß man sich nicht auch noch irgendwie den Vohergehenden Zustand der
Port-Pins merken und zusätzlich auswerten.
Denn wenn im ersten Interrupt P1.0 auf 1 geht, dann wird die Funktion
abgearbeitet.

Im nächsten Interrupt für Flanke von P1.1 wird dann aber wieder die
Funktion für P1.0 mit abgearbeitet, weil dieser ja noch immer 1 sein
könnte.

Oder seh ich da was falsch?

von Sebastian (Gast)


Lesenswert?

Genau darum geht es ja gerade. Das Flag wird entweder automatisch zurück
gesetzt, oder Mike muss das manuell machen. Keine Ahnung, wie das war,
hab ich vergessen. Steht aber sicherlich irgendwo im User Guide. Und
dann passiert das von dir beschriebene nicht.

von Ingo Henze (Gast)


Lesenswert?

Ich meine aber nicht das Interrupt-Flag, sondern den Zustand der
Port-Pins selber.

von Sebastian (Gast)


Lesenswert?

@Oldbug: Wieso machst du eigentlich einen Typecast?!

> switch ((int)P1IN)

Das ist doch überflüssig, da die Portpins eh byteweise ausgewertet
werden?!

von Sebastian (Gast)


Lesenswert?

> Ich meine aber nicht das Interrupt-Flag, sondern den Zustand der
> Port-Pins selber

Häh? Ja, das war mir schon klar. Und ich sage: Brauchst du nicht! Wenn
du das IR-Flag korrekt zurücksetzt, sollte dir der Zustand der Pins
völlig egal sein. Denn du triggerst ja auf FLANKEN, nicht auf ZUSTÄNDE!

von OldBug (Gast)


Lesenswert?

War mir nicht sicher, ob der IAR (weil ich selber nur gcc verwende), das
anmeckert (switch muss immer nach int "geswitched" werden, Register
sind aber als unsigned char definiert).

Also: nur zur Sicherheit, kann sein, daß das auch ohne Funktioniert und
nicht beanstandet wird. Hatte auch jetzt keine Lust, das extra
auszuprobieren g

Gruß,
Patrick...

von Ingo Henze (Gast)


Lesenswert?

Ja klar, getriggert wir auf Flanken, aber in der Interrup-Routine fragst
Du doch aber dei Zustände der Pins ab, um entsprechend zu
verzweigen.
if (P1IN|0x01) ...
if (P1IN|0x02) ...
Und die ändern sich nicht mit dem Zurücksetzen den Interrupt-Flags,
oder?

von Sebastian (Gast)


Lesenswert?

Völlig richtig. Das Abfragen der Zustände war ja auch nur so meine erste
Idee. Die ist aber suboptimal, wie sich mittlerweile herausgestellt
hat. Aber ist doch auch egal, Mikes Problem scheint ja gelöst zu sein.

von OldBug (Gast)


Lesenswert?

>Und die ändern sich nicht mit dem Zurücksetzen den Interrupt-Flags,
>oder?

Richtig! Das kann sogar "Fehler" verursachen. Beispiel:
Flankengetriggerter Interrupt auf P1.0 freigeschaltet
Flanke tritt auf
if(P1IN & 0x0X)... arie wird abgearbeitet, findet aber nie ein
Ergebnis, da die Flanke (und mglw. auch der Zustand des Pins) längst
nicht mehr repräsentativ ist.

Gruß,
Patrick...

von Ingo Henze (Gast)


Lesenswert?

Moment mal, dann hab ich das aber nicht verstanden :-)
Wie erfahre ich in der Interrupt-Routine, welcher meiner Eingänge am
Port den Interrupt ausgelöst hat?
Doch nur über den Zustand des Pins, oder?
Kann mir das bitte nochmal jemand erklären.

Danke!

von OldBug (Gast)


Lesenswert?

Über das Interrupt Flag Register (PxIFG).

von Sebastian (Gast)


Lesenswert?

@Ingo: Mach doch einen neuen Thread auf. Jetzt fangen hier zwei Leute
an, verschiedene Fragen zu stellen, das wird tierisch unübersichtlich.
Du stellst Fragen, die Mike schon längst geklärt hat, und ich blicke
bald gar nicht mehr durch ... ;-)

von Ingo Henze (Gast)


Lesenswert?

Also so, wie Mike es weiter oben selbst vorschlägt?
if((P1IFG&0x01)==1) ...
if((P1IFG&0x80)==1) ...

Na dann hab ich es wohl doch begriffen :-=
Danke!

von Mike (Gast)


Lesenswert?

ich sage nur verwirrung pur ;o)

Die Interrupts funktionieren glaube ich so langsam aber sicher. Muss
noch einwenig daran herumfeilen..

von OldBug (Gast)


Lesenswert?

Sowas kann man auch schlecht vermitteln. Ich vermute, daß es daran
liegt, daß derjenige, der sich gerade erst damit beschäftigt, ein
völlig falsches Bild von dem hat, was er da macht. Am vermittelnden (so
lange seine Aussagen richtig sind) liegts meistens nicht :-)

Gruß,
Patrick...

von Ingo Henze (Gast)


Lesenswert?

Ok, dann halte ich mich besser aus Sachen raus, von denen ich nicht
wirklich was verstehe, um nicht noch mehr Verwirrung zu stiften.
"Schuster bleib bei deinen Leisten", ich bleib dann doch erstmal bei
meinen AVRs :-)

von Sebastian (Gast)


Lesenswert?

@Mike: Hat sich eigentlich mittlerweile was ergeben? Klappen deine
flankengetriggerten Interrupt-Routinen? Ich bräuchte sowas jetzt
nämlich auch, und wenn dein Code funktioniert, wäre es nett, wenn du
ihn mal hier posten könntest. Man muss das Rad ja nicht zwei mal
erfinden. Insbesondere, was das IR-Flag angeht; du hast ja mittlerweile
bestimmt rausgefunden ob es automatisch resettet wird ;-)

von Mike (Gast)


Lesenswert?

Hallo Sebastian, ja, funktioniert alles einwandfrei. Dann kann ich ja
auch dir mal helfen ;o)
Das Flag muss mit der Software geresetet werden...

Der Code sieht folgendermassen aus:

_BIS_SR(GIE);         //algemeiner Interrupt enable
P1IE|=0x01;           // P1.0 ist jetzt Interrupt-fähig
P1IES|=0x00;          // Interrupt bei low-->high Übergang=0



//Interrupt Routine

#pragma vector=PORT1_VECTOR
__interrupt void Port1_Interrupt (void)
{
if((P1IFG&0x01)==0x01)   //Wenn Flag von P1.0 gesetzt ist
    {
    Anweisungen;
    }

P1IFG=0;   //Inerruptflag zurücksetzen
}


Gruss Mike

von Sebastian (Gast)


Lesenswert?

Hi Mike,

das mit dem resetten hatte ich mittlerweile auch im User's Guide
nachgelesen -- in der Tat, das Ding muss manuell resettet werden.
Komisch, beim USART geht das ja automatisch ...

Ich grübele gerade noch über dem GIE-Bit. Weisst du eigentlich, ob das
nach einem Power-On per default gesetzt ist? Ich schicke meinen MSP430
in den LPM3 mit GIE (_BIS_SR(LPM3_bits + GIE);), da ist es mir eh egal,
aber falls ich das mal nicht mache, müsste ich ja dann aufpassen, immer
zuerst das GIE zu setzen, falls es nicht sowieso per default gesetzt
ist.

Welche IDE benutzt du noch mal? IAR? Und wo hast du die Namen des
IR-Vektors her? Ich hab da zum Verrecken nix gefunden. OK, die Namen
sind ziemlich logisch, die hätte ich auch erraten können, aber da muss
es doch irgendwo eine Übersicht geben?! Oder hast du das einfach aus
dem Header-File "erraten"?

von Mike (Gast)


Angehängte Dateien:

Lesenswert?

nein, die Vektoren sind in dem slas... file (seite9), welches ich dir
angehängt habe.danach habe ich mit der adresse im headerfile
nachgeschaut und den verwendbaren Vektor gefunden.
Wegen dem Power up habe ich leider keine Ahnung, aber du kannst das GIE
ja immer setzten, wenn du einen Interrupt brauchst.

von OldBug (Gast)


Lesenswert?

Btw.: DAS sieht ziemlich unübersichtlich aus:

>//Interrupt Routine
>
>#pragma vector=PORT1_VECTOR
>__interrupt void Port1_Interrupt (void)
>{

Besser die Makros verwenden:

interrupt[PORT1_VECTOR] void Port1_Interrupt (void)
{
    /* something */
}

für IAR, oder für gcc:

interrupt(PORT1_VECTOR) void Port1_Interrupt (void)
{
    /* something */
}

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.