mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik interrupt LowPowerMode MSP430F449


Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich glaube ich habe einen Denkfehler in meiner Interruptrotine.
Kann mir jemand auf die Sprünge helfen?
Ich möchte wenn am Port1.3 ein Interrupt ansteht einen Zähler erhöen und 
danach den MSP sofort wieder schlafen legen. Jedoch komme ich nach dem 
ersten Interrupt nie mehr in die Interruptroutine...
#pragma interrupt_handler port1_isr:PORT1_VECTOR
void port1_isr(void)
{
    if(get_bit(P1IFG, BIT3)){
        if(get_bit(P1IES, BIT3)){
            // Interrupt wurde durch eine negative Flanke ausgelöst
            LPM3_EXIT;
        if(flow_counter >= 65535){
          flow_counter_old = 0;
          flow_counter = 1;
          LPM3;
        }else{
          flow_counter++;
          LPM3;
        }
        }
    }
    P1IFG = 0;
}


Bin um jede Hilfe dankbar.

MFG Fabio

Autor: slw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Code paßt nicht zu Deiner Aussage, dass Du nie mehr aus der ISR 
rauskommst. Ich bin mir fast sicher dass Du immer wieder diese Routine 
ausführst. Denn es fehlt ein "Clear Interrupt Flag" befehl! Sprich wenn 
ein IRQ Flag gesetzt bleibt, läuft die ISR in einer "Endlos Schleife" 
ab.

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

Bewertung
0 lesenswert
nicht lesenswert
Soll das wirklich so sein?
void port1_isr(void)
{
  if (get_bit(P1IFG, BIT3))
  {
    if (get_bit(P1IES, BIT3))
    {
      // Interrupt wurde durch eine negative Flanke ausgelöst
      LPM3_EXIT;
      if (flow_counter >= 65535)
      {
        flow_counter_old = 0;
        flow_counter = 1;
        LPM3;
      }
      else
      {
        flow_counter++;
        LPM3;
      }
    }
  }
  P1IFG = 0;
}

Irgendwie habe ich das Gefühl, daß Du da mit den Klammern und Deiner 
Sourcecodeformatierung durcheinandergekommen bist.

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal für eure Antworten:

@slw

Du meinst wenn ich das LPM3 flag setze wird das P1IFG = 0; nie mehr 
ausgeführt und somit bleibe ich endlos in dieser Routine gefangen?

@ Rufus Τ. Firefly

ich denke ja, aber kann sein dass ich etwas übersehe. Ich versuchs mal 
zu erklären.

1. IF-Abfrage ist ein Interrupt an Port1.3 aufgetreten
2. IF-Abfrage war es eine negative Flanke, falls ja, CPU hochfahren --> 
LPM3_EXIT;

3. IF-Abfage flow_counter auf Überlauf prüfen
4. Alle Interrupt-Flags des Port1 zurücksetzen.

Ich habe eine Anwendung in der ich möglichst wenig Strom verbrauchen 
soll, da Batteriebetrieben. Ein Geber sendet mir auf Port1.3 sporadisch 
Flanken. Diese Flanken will ich zählen. Über den Basic_Timer fahre ich 
alle 30min externe Speisungen hoch und setze per RF ein Telegramm ab.

Ich steh heute wohl auf der Leitung.

Autor: slw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich kenne die genaue Bezeichnungen von den einzelnen Flags nicht, jedoch 
das erste was passieren soll, wenn ein ISR ausgeführt wird, Flag zu 
löschen, der für das anspringen der ISR verantwortlich ist. Wie dieser 
zurück gesetzt wird, steht sicherlich im DB, schau nochmal genau nach.

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

Bewertung
0 lesenswert
nicht lesenswert
Auf LPM3_EXIT folgt in Deinem Code unweigerlich ein LPM3 -- ich habe 
Deinen Code nur umformatiert, aber nicht inhaltlich geändert.

Deswegen frage ich ja, ob Du Dir da wirklich sicher bist.

Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo codehamster,

ich verstehe eins nicht ; wenn  ein interrupt an PortX
warum den "If " Handling ?
bei Assembler wird der interrupt handling ausgeführt und dann
weiter in der Hauptschleife.
Ich mache nur assembler ist das bei C anders?

mfg Erik

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

@slw:
jep da bin ich grundsätzlich deiner Meinung! ev. wäre es besser die 
einzelnen Flags zurückzusetzen, anstatt am Ende der ISR alle Flags 
gleichzeitig.

@Rufus Τ. Firefly:
ich hab gemekrt dass du "nur" umformatiert hast. Auf deine Bemerkung 
dass unweigerlich auf LPM3_EXIT ein LPM3 kommt kann ich nur sagen dass 
ich mir eben nicht sicher bin ob dass so funktionieren kann.
Dazu stellen sich zwei Fragen. Die 1. hat slw schon angesprochen, 
Interruptflags gleich löschen sobald die Bearbeitungsroutine anspringt.
Die 2. Frage die sich mir stellt, gibt es ein minimale Dauer die es 
abzuwarten gilt bis die CPU, und diverse Clocks wieder hochgefahren 
sind, oder ist nach LPM3_EXIT der Prozessor schon wieder bereit 
Arithmetische operationen durchzuführen.
Nach meinen Überlegungen ist ja die Arbeit nach dem inkrementieren, bzw. 
Rücksetzen der Zählerstände erledigt. Desshalb sofort wieder in den 
LPM3.
Aber ich vermute dass da der Hund begraben liegen könnte.

@Erik:
das P1IFG ist das Port 1 Interrupt Flag Register. Wenn an einem der 
Pin's von diesem Port welche für Interrupts freigegeben sind anspricht, 
wird in diese ISR gesprungen. Die IF's sind dazu da um herauszubekommen 
welcher der 8 möglichen Pin's des Ports den Interrupt ausgelöst hat. Man 
hat ja nicht 8 mögliche Interruptquellen wenn eine reichen würde.
Nach Beendigung der ISR wird wieder in der Hauptschleife 
weitergearbeitet, das ist in C nicht anders als in Assembler.

Vielen Dank für Eure Feedbacks, ev. habt Ihr noch einen Tipp für mich, 
ich werde auf jeden Fall nochmal den User-Guide wälzen.

MFG Fabio

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einem Interrupt wird der MSP430 automatisch aufgeweckt und nach 
Beendigung der Interrupt Service Routine auch wieder schlafen gelegt 
wenn er vorher in einem low power mode war. LPM3_EXIT und LPM3 
Anweisungen brauchts dafür nicht.

Mit P1IES (Port 1 interrupt edge select) wird festgelegt ob eine 
positive Flanke (0) oder eine negative Flanke (1) am Pin den Interrup 
auslösen können soll.
P1IES muss entsprechend initialisiert werden, am besten bevor Interrupts 
erlaubt werden.
Eine Prüfung von P1IES in der ISR sollte normalerweise nicht notwendig 
sein.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Prüfung, welche Flanke den Interrupt ausgelöst hat ist auch gar 
nicht möglich. Der MSP430 kann nur ent oder weder. Und das muss man 
vorher einstellen. Das LPM3_EXIT braucht man, wenn der MSP nach der ISR 
noch wach sein soll. IFG löschen ist richtig, soweit ich mich erinnere, 
werden die Port-IFGs nicht automatisch gelöscht.

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

danke für eure Ausführungen! Hab auch nochmal im User-Guide gestöbert.
Also kurz zusmamengefasst:
- Das Abfragen des EdgeSelectRegisters ist unnötig.
- Ein Interrupt (sofern Freigegeben) weckt die CPU und nach Beendigung 
der ISR wird wieder in den ursprünglichen "Operating Mode" gegangen.

Somit bleibt noch die Frage Interuptflag löschen, am Ende der ISR oder 
beim Beginn der ISR?
void port1_isr(void)
{
  if (get_bit(P1IFG, BIT3))
  {
    if (flow_counter >= 65535)
    {
      flow_counter_old = 0;
      flow_counter = 1;
    }
    else
    {
      flow_counter++;
    }
    clr_bit(P1IFG, BIT3);
  }
}


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

Bewertung
0 lesenswert
nicht lesenswert
Fabio S. schrieb:
> if (flow_counter >= 65535)

Was für einen Datentyp hat denn bitte flow_counter?

Autor: codehamster (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned int16

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

Bewertung
0 lesenswert
nicht lesenswert
Hmm. Kann ein unsigned int16 größer werden als 65535?

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus Τ. Firefly schrieb:
> Hmm. Kann ein unsigned int16 größer werden als 65535?

nein =), das geht somit auch kürzer! Danke für den Hinweis.

somit wären alle Fragen geklärt.
Danke für eure Hilfe.

MFG Fabio

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

Bewertung
0 lesenswert
nicht lesenswert
Dann bleibt die Frage, was Du eigentlich mit Deiner Funktion bezweckst. 
Geht es um die Erkennung eines Overflow?

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rufus,

Fabio S. schrieb:
> Ich habe eine Anwendung in der ich möglichst wenig Strom verbrauchen
> soll, da Batteriebetrieben. Ein Geber sendet mir auf Port1.3 sporadisch
> Flanken. Diese Flanken will ich zählen. Über den Basic_Timer fahre ich
> alle 30min externe Speisungen hoch und setze per RF ein Telegramm ab.

Also bezwecke ich damit nichts anderes als Interruptgesteuert einen 
Zähler zu bedienen. Kann kürzer behandelt werden als in meinem 
Codeschnippsel, wie du ja bereits bemerkt hast.

Es geht darum dass in einer gewissen Zeit eine gewisse anzahl Impulse 
gezählt werden müssen. Da das System Batteriebetrieben wird, Zählen per 
Interrupt. Ansonsten soll der MSP schlafen und alle xmin ein Telegramm 
absetzen.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na hoffentlich hast du das Zählsignal ordentlich entprellt...

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab ich =)

bin ja zum Glück nicht mehr ganz so grün hinter den Ohren.
Aber trotzdem musste ich feststellen das ich im Thema Interrupt und 
Operating-Modes des MSP430 noch einiges zu lernen habe.

Danke für eure Feedbacks.
wünsche einen schönen Tag.

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.