mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ISR - optimale Programmstruktur (MPS430 C-Code)


Autor: Jürgen R. (duke)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

wie sieht eine optimale Programmstruktur mit Interrupts / ISR aus?

Ich lese oft, dass die ISR so kurz wie möglich gehalten werden soll.
Meistens sind jedoch noch weitere Berechnungen durchzuführen.

Ist die unten gezeigte Struktur ok oder gibt es noch 
Optimierungspotential?

Weiterhin suche ich eine Möglichkeit die Interruptauslastung 
auszumessen. Hat jemand eine Software Lösung?

Beispiel C-code für MSP430
// #includes, #defines etc.

void main(void) //wird nur einmal nach power on reset durchlaufen
{
// Initialisierung BasicTimer1
// erzeugt alle 976,5µs einen Interrupt

// sowie sonstige Initialisierungen
goto_lpm();
}


void goto_lpm(void)
{
// µC in Low Power Mode (LPM) versetzen
}


#pragma vector=BASICTIMER_VECTOR
__interrupt void basic_timer_ISR(void) //Aufruf alle 976,5µs
{
_DINT(); // keine weiteren Interrupts zulassen

if (10mal aufgerufen)   // dann 10ms_Flag setzen
if (1024mal aufgerufen) // dann 1000ms_Flag setzen

after_ISR();

_EINT(); // Interrupts wieder zulassen
}


// wird nach jedem ISR durchlaufen
// max. Bearbeitungszeit 976µs
void after_ISR() 
{
if (10ms Flag gesetzt?)
  {
    // hier alles rein was alle 10ms erledigt werden muss
    // z.B. Schalter abfragen, Sensoren abtasten etc. 
  }
if (1000ms Flag gesetzt?)
  {
    // hier alles rein was jede Sekunde erledigt werden muss
    // z.B Uhr aktualisieren (Sekunde++) etc.
  }
// hier geht der µC wieder automatisch in LPM
}

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach goto_lpm läuft Dein Programm aus dem Main raus - ganz schlecht!
Da gehört ne Endlosschleife drumrum.


"goto" ist ein Schlüsselwort, besser nicht als Namen verwenden.


Wenn Du im Interrupt trotzdem die Funktionen aufrufst, kannst Du Dir das 
Flag setzen schenken.
Flags machen nur Sinn, wenn die langwierige Behandlung im Main erfolgt.


Peter

Autor: Ampfing (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jürgen,

wie Peter schon sagte, das Flag-Setzen macht nur anders Sinn. In etwa 
so:
void main()
{
  //Initialisieren der HW

  while(1)
  {
    if (10ms_Flag == 1)
    {
       //alles was nach 10 ms getan werden soll tun
    }
    if (1000ms_Flag == 1)
    {
       //alles was nach 1000ms getan werden soll
    }
    schlafen_legen();
   }
}

Wenn mich nicht alles täuscht kannst Du Dir das _DINT() und _EINT() in 
der ISR sparen, das macht der MSP430 automatisch.

Viele Grüße

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jürgen R. (duke)

>Weiterhin suche ich eine Möglichkeit die Interruptauslastung
>auszumessen. Hat jemand eine Software Lösung?

Nee, aber Hardware (bin Hardwerker ;-)
Einfach zum Beginn der Interruptroutine ein IO-Pin auf HIGH setzen, am 
Ende wieder auf Low. Damit sieht man am Oszi schön, wann und wie oft der 
Interrupt auftritt. Und über eien RC-Filter + Multimeter kann man damit 
auch die Prozessorlast messen, quasi [PWM]].

MFG
Falk

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies dir mal diese AppNote durch: http://www.ti.com/litv/pdf/slaa294a

Autor: Jürgen R. (duke)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

vielen Dank für die zahlreichen Tipps!

@Peter
"Nach goto_lpm läuft Dein Programm aus dem Main raus - ganz schlecht!"
Die haupt_routine() ist immer noch ausserhalb der main(),
ist das im unten gezeigten Code noch ein Problem?

@Falk
danke für die HW Lösung, die war mir schon bekannt.:-)
Wie kann ich sicherstellen (messen) dass ich keinen Interrupt auslasse?
Angenommen die haupt_routine() dauert so lange, dass schon wieder ein 
Interrupt ansteht.


Ich habe meine Struktur wie folgt angepasst.
Es würde mich freuen, wenn Ihr mir hiezu noch euren Kommentar geben 
könnt.
// #includes, #defines etc.

void main(void) //wird nur einmal nach power on reset durchlaufen
{
// Initialisierung BasicTimer1
// erzeugt alle 976,5µs einen Interrupt

// sowie sonstige Initialisierungen
// alles was vor der Hautproutine nur einmalig passiert

haupt_routine();
}

void haupt_routine(void)
{
  for (;;)  // Hauptschleife forever
  {
    // hier wird auch nach der ISR weitergemacht
    // ggf. µC-Pin setzen für Laufzeitmessung

    if (10ms Flag gesetzt?)
    {
      // hier alles rein was alle 10ms erledigt werden muss
      // z.B. Schalter abfragen, Sensoren abtasten etc. 
    }
    if (1000ms Flag gesetzt?)
    {
      // hier alles rein was jede Sekunde erledigt werden muss
      // z.B Uhr aktualisieren (Sekunde++) etc.
    }

    // ggf. µC-Pin rücksetzen für Laufzeitmessung

    LPM3; // µC in Low Power Mode (LPM) versetzen
  }
}


#pragma vector=BASICTIMER_VECTOR
__interrupt void basic_timer_ISR(void) 
{
 // Aufruf alle 976,5µs
 // In der ISR NUR Flags setzen!

 if (10mal aufgerufen)   // dann 10ms_Flag setzen
 if (1024mal aufgerufen) // dann 1000ms_Flag setzen

 LPM3_EXIT; // erst mal wach bleiben
}

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.