Forum: Mikrocontroller und Digitale Elektronik MSP430 Probleme mit Interrupt-Routine


von reflection (Gast)


Lesenswert?

Hallo zusammen

Ich habe wieder mal ein Problem mit meinem MSP. Irgendwie habe ich das 
schon so gemacht (glaube ich zu mindest) aber es will einfach nicht 
mehr.

Folgendes:

Ich habe am MSP430F149 ein eDIP240 Display mit Touch dran. Dies besitzt 
einen Pin der mir anzeigt wenn eine Touch-Taste gedrückt wurde. Diesen 
habe ich, da 5V, über einen Transistor der als Levelshifter fungiert, an 
meinen MSP430 (3.3V) angeschlossen. Klappt auch wunderbar, die Logik ist 
halt nun umgedreht. Das Display zieht auf Low wenn eine Taste gedrückt 
wird, Transistor sperrt, also High am Pin 1.2 des MSP. Den Port habe ich 
auf steigende Flanke eingestellt. So nun hier der Code (Auszug)

void Init_ports(void)
{
P1SEL &= 0xE0;    // P1.0 - P1.4 als I/O konfigurieren
P1DIR = 0xE0;    // P1.0 - P1.4 als Input definieren
P1IES = 0x0B;          // P1.2 pos. edge löst Interrupt aus
P1IE = 0x04;    // P1.2 kann Interrupt auslösen
}

Auszug aus Main:

interrupt (PORT1_VECTOR) P1_ISR(void)
{
    if(P1IFG & 0x01)    // hat P1.0 den Interrupt ausgelöst?
    {
         P1IFG = 0x00;    // Interrupt-Flag löschen
    }
    else if(P1IFG & 0x02)  // hat P1.1 den Interrupt ausgelöst?
    {
      P1IFG = 0x00;    // Interrupt-Flag löschen
    }
    else if(P1IFG & 0x04)  // hat P1.2 den Interrupt ausgelöst?
    {
      test_irq += 1;
      P1IFG = 0x00;    // Interrupt-Flag löschen
    }
    else if(P1IFG & 0x08)  // hat P1.3 den Interrupt ausgelöst?
    {
        P1IFG = 0x00;    // Interrupt-Flag löschen
    }
    else if(P1IFG & 0x10)  // hat P2.4 den Interrupt ausgelöst?
    {
         P1IFG = 0x00;    // Interrupt-Flag löschen
    }
    else      // Bei mehreren Interrupts --> keine Aktion
    {
         P1IFG = 0x00;    // Alle Interrupt-Flags löschen
    }
}

So, nun müsste ja bei einem Interrupt eigentlich die Variable test_irq 
um 1 erhöht werden... MÜSSTE :o)

Wenn ich einen Breakpoint auf die Zeile:

interrupt (PORT1_VECTOR) P1_ISR(void)

setze, hält er genau dort an wenn ich eine Taste auf dem Touch drücke.

aber die Variable test_irq wird nicht erhöht. Auch wenn ich einen 
Breakpoint auf else if(P1IFG & 0x04) setzte, oder direkt auf test_irq += 
1; hält er nie an.

Sieht jemand vielleicht einen Fehler, oder kann bestätigen, dass es so 
gehen müsste? Bin um jede Hilfe froh.

Gruss reflection

von reflection (Gast)


Lesenswert?

Jetzt wirds richtig lustig. Habe mal in jede Abfrage eine Variabel 
reingehängt die um 1 erhöht wird bei einem Interrupt. Mein Display hängt 
an P1.2 zu 100%, wenn ich einen Breakpoint auf if(P1IFG & 0x01) setzte, 
dann springt er bei einem Inerrupt dort hinein. Er müsste doch aber in 
P1IFG & 0x04) reinspringen für P1.2????

Gruss reflection

von Tobias K. (kurzschluss81)


Lesenswert?

Hallo
Also als erstes wenn du Ports als Eingang nehmen wilst deweiteren normal 
als I/O dann brauchst das nicht extra einstellen.
gleiches gilt für die FLankeneinstellung für Pin1.2 der ist standart auf 
steigende Flanke eingestellt. Muste mal im Userguide reinschauen.
Diese "Standarts muss man nicht einstellen.

und als nächstes verstehe ich nicht wozu du diese aufwändige Interrup 
flag abfrage machst.
Nur ein Signal auf dem Pin 1.2 kann einen Interrupt auslösen. die 
anderen nicht. Also kommt auch nur ein Interrupt wenn auf Pin 1.2 was 
rumwackelt.

und zuletzt für die Interrupt serviseruotine

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wo und wie ist test_irq definiert?

von reflection (Gast)


Lesenswert?

Hallo zusammen

test_irq ist Global definiert und mit 0 initialisiert.

Klar kann in diesem Fall nur P1.2 einen Interrupt auslösen, habe ich zu 
Testzwecken so eingestellt weil ich sicherstellen will, das nicht irgend 
ein anderer Pin dazwischenfunkt. Wie würdest Du den die Abfrage machen 
wenn es mehrere Pins sind die einen Interrupt auslösen können?

Gruss reflection

von reflection (Gast)


Lesenswert?

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)

funzt bei mir nicht. Habe Eclipse und mspgcc

Gruss

von Christian R. (supachris)


Lesenswert?

Was zeigt P1IFG denn an, wenn du den Breakpoint auf die erste Zeile der 
ISR setzt? Bist du wirklich ganz sicher, dass du richtig angeschlossen 
hast?
ISR Deklaration ist für GCC natürlich völlig korrekt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> test_irq ist Global definiert und mit 0 initialisiert.

Aber nicht als volatile. Wenn Du in Deiner Interruptroutine darauf 
zugreifst, und auch aus Deiner main-Funktion, dann weiß der Compiler 
nichts davon und kann durchaus Lesezugriffe auf die Variable 
wegoptimieren, weil er nicht davon ausgeht, daß die Variable sich quasi 
"hinter seinem Rücken" ändern kann. Mit volatile aber wird dem 
Compiler gesagt, daß er keinerlei Annahmen über den Wert der Variablen 
treffen soll.

von reflection (Gast)


Lesenswert?

selbst wenn er es wegoptimiert dürfte er nicht in if(P1IFG & 0x01) 
reinspringen.

Werde morgen schauen was im P1IFG drinsteht. Die ganze Sache kommt mir 
einfach spanisch vor.

Das Layout stimmt, ist ein Board welches ich herstellen liess. Habe die 
Daten noch einmal kontrolliert. Habe es auch auf unterschiedlichen 
Boards getestet. Der MSP macht immer das selbe. :o( Bis jetzt hatte ich 
immer nur Taster, oder Interrupts an Port 2 angeschlossen. Irgend einen 
Unterschied gibt es doch da in der Interruptbehandlung, oder hab ich da 
was falsches im Kopf?

Gruss reflection

von Tobias K. (kurzschluss81)


Lesenswert?

> Klar kann in diesem Fall nur P1.2 einen Interrupt auslösen, habe ich zu
> Testzwecken so eingestellt weil ich sicherstellen will, das nicht irgend
> ein anderer Pin dazwischenfunkt. Wie würdest Du den die Abfrage machen
> wenn es mehrere Pins sind die einen Interrupt auslösen können?
>
> Gruss reflection

Am einfachsten geht das mit einer Switch Case Anweisung. Aber das 
funktioniert nur wenn du immer nur ein Bit gleichzeitig gesetzt wird. 
wenn mehrere gesetzt werden und du das alles einzeln prüfen möchtest 
dann wird eine Switch case Anweisung etwas umfangreicher. Dann ist deine 
Losung so falsch nicht.

Aber auch wenn du ganz sicher gehen willst das in deinem Fall kein 
andere Pin daswischen funkt, würde eine If Abfrage reichen.

interrupt (PORT1_VECTOR) P1_ISR(void)
{
    if(P1IFG & 0x04)  // hat P1.2 den Interrupt ausgelöst?
    {
      test_irq += 1;

    }
    P1IFG = 0x00;    // Alle Interrupt-Flags löschen
}

Ich nutze auch Eclipse aber in Zusammenhang mit Code Composer 3.2 .
Ich hatte nicht bedacht das die alten Versionen und das andere mit 
MSPGCC noch ein paar andere Eigenheiten haben.

von reflection (Gast)


Lesenswert?

Hallo zusammen

Ich habe das Problem erkannt und den Fehler behoben.

Folgendes:

Der Tipp das P1IFG Register anzuschauen war der Hinweis den ich 
benötigte. Inhalt 37dez = 00100101bin also hat P1.2 tatsächlich eine 1 
drin, aber Port 2.0 halt eben auch. Wieso das so ist, k.A :o) Ich habe 
jetzt in der Portinitialisierung auch noch das P1IFG Register mit 0x00 
initialisiert und schon rumst die Kiste.

Merci für die Tipps

Gruss reflection

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.