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


von Jürgen R. (duke)


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
1
// #includes, #defines etc.
2
3
void main(void) //wird nur einmal nach power on reset durchlaufen
4
{
5
// Initialisierung BasicTimer1
6
// erzeugt alle 976,5µs einen Interrupt
7
8
// sowie sonstige Initialisierungen
9
goto_lpm();
10
}
11
12
13
void goto_lpm(void)
14
{
15
// µC in Low Power Mode (LPM) versetzen
16
}
17
18
19
#pragma vector=BASICTIMER_VECTOR
20
__interrupt void basic_timer_ISR(void) //Aufruf alle 976,5µs
21
{
22
_DINT(); // keine weiteren Interrupts zulassen
23
24
if (10mal aufgerufen)   // dann 10ms_Flag setzen
25
if (1024mal aufgerufen) // dann 1000ms_Flag setzen
26
27
after_ISR();
28
29
_EINT(); // Interrupts wieder zulassen
30
}
31
32
33
// wird nach jedem ISR durchlaufen
34
// max. Bearbeitungszeit 976µs
35
void after_ISR() 
36
{
37
if (10ms Flag gesetzt?)
38
  {
39
    // hier alles rein was alle 10ms erledigt werden muss
40
    // z.B. Schalter abfragen, Sensoren abtasten etc. 
41
  }
42
if (1000ms Flag gesetzt?)
43
  {
44
    // hier alles rein was jede Sekunde erledigt werden muss
45
    // z.B Uhr aktualisieren (Sekunde++) etc.
46
  }
47
// hier geht der µC wieder automatisch in LPM
48
}

von Peter D. (peda)


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

von Ampfing (Gast)


Lesenswert?

Hallo Jürgen,

wie Peter schon sagte, das Flag-Setzen macht nur anders Sinn. In etwa 
so:
1
void main()
2
{
3
  //Initialisieren der HW
4
5
  while(1)
6
  {
7
    if (10ms_Flag == 1)
8
    {
9
       //alles was nach 10 ms getan werden soll tun
10
    }
11
    if (1000ms_Flag == 1)
12
    {
13
       //alles was nach 1000ms getan werden soll
14
    }
15
    schlafen_legen();
16
   }
17
}

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

von Falk B. (falk)


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

von Christian R. (supachris)


Lesenswert?

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

von Jürgen R. (duke)


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.
1
// #includes, #defines etc.
2
3
void main(void) //wird nur einmal nach power on reset durchlaufen
4
{
5
// Initialisierung BasicTimer1
6
// erzeugt alle 976,5µs einen Interrupt
7
8
// sowie sonstige Initialisierungen
9
// alles was vor der Hautproutine nur einmalig passiert
10
11
haupt_routine();
12
}
13
14
void haupt_routine(void)
15
{
16
  for (;;)  // Hauptschleife forever
17
  {
18
    // hier wird auch nach der ISR weitergemacht
19
    // ggf. µC-Pin setzen für Laufzeitmessung
20
21
    if (10ms Flag gesetzt?)
22
    {
23
      // hier alles rein was alle 10ms erledigt werden muss
24
      // z.B. Schalter abfragen, Sensoren abtasten etc. 
25
    }
26
    if (1000ms Flag gesetzt?)
27
    {
28
      // hier alles rein was jede Sekunde erledigt werden muss
29
      // z.B Uhr aktualisieren (Sekunde++) etc.
30
    }
31
32
    // ggf. µC-Pin rücksetzen für Laufzeitmessung
33
34
    LPM3; // µC in Low Power Mode (LPM) versetzen
35
  }
36
}
37
38
39
#pragma vector=BASICTIMER_VECTOR
40
__interrupt void basic_timer_ISR(void) 
41
{
42
 // Aufruf alle 976,5µs
43
 // In der ISR NUR Flags setzen!
44
45
 if (10mal aufgerufen)   // dann 10ms_Flag setzen
46
 if (1024mal aufgerufen) // dann 1000ms_Flag setzen
47
48
 LPM3_EXIT; // erst mal wach bleiben
49
}

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.