Forum: Mikrocontroller und Digitale Elektronik MSP430F1611- gegenseitige Beeinflussung der Timer?


von Wolle G. (wolleg)


Angehängte Dateien:

Lesenswert?

Ich möchte z.B. Timer A als Taktgeber (7,5ms) für die Abtastung des 
A/D-Wandlers verwenden und den Spannungswert als Kurve (EKG) auf einem 
LCD darstellen. (funktioniert)
Durch Auswertung der Zeit zwischen 2 EKG-Spannungsspitzen soll der Puls 
ermittelt und der Wert auch mit angezeigt werden.
Dazu wollte ich mit Timer B über den cap-Modus die Zeit zwischen 2 
Spannungsspitzen ermitteln.
In einigen Vorversuchen habe ich festgestellt, dass dann, wenn Timer A 
in Betrieb ist, die Zeitangaben des Timer B schwanken.
Wird nur Timer B verwendet, ist die von Timer B ermittelte Zeit korrekt.
Im Anhang das  Programm, mit dem ich getestet habe.
Noch eine Ergänzung: Mit Timer A wird hier nur eine LED EIN/AUS 
geschaltet. Ist die Verzögerung < ca. 9000x 125ns =1,125ms läuft Timer B 
richtig, was ich so deute, dass sich die Timer gegenseitig beeinflussen.
Zur eigentlichen Frage: kann man die gegenseitige Beeinflussung 
beseitigen, wenn ja, wie

von isr_checker (Gast)


Lesenswert?

villeicht sind deine Routinen in den ISRs zu lang

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du hat in Deiner ISR eine Verzögerungsschleife?

Das ist ungeschickt.

Warum invertierst Du nicht einfach bei jedem Aufruf der ISR das die LED 
ansteuernde Portbit?

Statt

> P5OUT &= ~BIT7;  //LED rot EIN
> __delay_cycles(9000);
> P5OUT |= BIT7;  //LED rot AUS

also

P5OUT ^= BIT7;


Hast Du Dir mal die Interruptprioritäten der beiden genutzten Interrupts 
angesehen? Wenn TIMERA0 eine höhere Priorität hat als TIMERB1, blockiert 
Deine Verzögerungsschleife die ISR des TimerB.

Prinzipiell sollte man eine ISR so schnell wie möglich wieder verlassen 
und nie zeitraubende Dinge darin anstellen.

: Bearbeitet durch User
von Wolle G. (wolleg)


Angehängte Dateien:

Lesenswert?

Rufus Τ. F. schrieb:
> Du hat in Deiner ISR eine Verzögerungsschleife?
> Das ist ungeschickt.
> Warum invertierst Du nicht einfach bei jedem Aufruf der ISR das die LED
> ansteuernde Portbit?

Die Verzögerungsschleife + LED war nur als eine Art Stellvertreterrolle 
gedacht.
Mich macht allerdings stutzig, dass schon ca. 1,1ms reichen, um die 
eingestellten 10ms  des Timertaktes zu überschreiten (falls ich richtig 
gerechnet habe: XT2  Quarz 8MHz-->__delay_cycles(1); == 125ns; richtig?)

>Hast Du Dir mal die Interruptprioritäten der beiden genutzten Interrupts
>angesehen? Wenn TIMERA0 eine höhere Priorität hat als TIMERB1, blockiert
>Deine Verzögerungsschleife die ISR des TimerB.

Ich hatte gedacht, jeder Timer arbeitet separat und hatte deshalb extra 
zwei Timer verwendet. (Irtum)

Interrupt und Interruptprioritäten sind hier offensichtlich die 
Stichworte.

Ich habe jetzt mal versucht, mich etwas tiefer damit zu beschäftigen.
So, wie ich es jetzt sehe, wird mein Ansatz nicht funktionieren bzw. ich 
habe keine Lösungsidee.

Im Anhang das eigentliche Programme, bei dem die Darstellung der Kurve 
funktioniert.
Bei diesem Programm wurde auch die Fragestellung aus 
Beitrag "LCD DEM240160 mit UC1698 wie Bildspeicher auslesen" berücksichtigt.

Der Puls sollte zusätzlich auf dem grafischen LCD angezeigt werden. Die 
Ziffern werden aus 24x18 Bildpunkten erzeugt (funktioniert schon)
Die Pulsberechnung in der Funktion -void puls_berechnen(void)- 
funktioniert zwar, aber der Puls fällt zu hoch aus. Deshalb sollte Timer 
B ins Spiel kommen.

Gibt es evtl. eine (andere) Lösung für mein Problem?

von isr-checker (Gast)


Lesenswert?

>Ich hatte gedacht, jeder Timer arbeitet separat und hatte deshalb extra
>zwei Timer verwendet. (Irtum)

Die Timer sind unabhängig voneinander.

von Clemens L. (c_l)


Lesenswert?

wolle g. schrieb:
> Ich hatte gedacht, jeder Timer arbeitet separat und hatte deshalb extra
> zwei Timer verwendet. (Irtum)

Die Timer sind unabhängig.

Aber du hast nur eine CPU, und kannst nur einen Interrupt-Handler auf 
einmal ausführen.

> Interrupt und Interruptprioritäten sind hier offensichtlich die
> Stichworte.

Die Prioritäten sind nur dann relevant, wenn mehrere Interrupt-Flags 
gesetzt sind, und die CPU entscheiden muss, welcher Handler als nächstes 
dran kommt. Wenn ein Handler schon ausgeführt wird, wird er nicht mehr 
unterbrochen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Clemens L. schrieb:
> Wenn ein Handler schon ausgeführt wird, wird er nicht mehr unterbrochen.

Der MSP430 kennt auch "interrupt nesting", dazu muss im 
Interrupthandler, der unterbrochen werden können soll, das globale 
Interruptflag gesetzt werden (wofür es die /eint/-Instruktion gibt, was 
wiederum für gcc und IAR mit __enable_interrupt() verwendbar ist).


Im vorliegenden Fall aber wäre das herumdoktern am eigentlichen Symptom 
- der Warteschleife in der ISR.

von Wolle G. (wolleg)


Lesenswert?

Rufus Τ. F. schrieb:
> Im vorliegenden Fall aber wäre das herumdoktern am eigentlichen Symptom
> - der Warteschleife in der ISR.
Die Warteschleife sollte eigentlich vom Tisch sein und wurde durch:

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
    {
     EKG ();
      if (x_wert >240)
     {
      FKA_loeschen();
      x_wert=0;
     }
      x_wert=x_wert+1; //x-Achse wandert
     }
ersetzt. (in EKG8_IARP63V01.c)

Den Flankenabstand wollte ich mit:

#pragma  vector=TIMERB1_VECTOR
__interrupt void Timer_B1 (void)
   {
    flankenabstand = TBCCR1;
    TBCTL |=  TBCLR;
    TBCCTL1 &=~CCIFG;
    ausgabe_puls();
   }
bestimmen und daraus den Puls berechnen. (aus 0003-IAR-TS_Zeit_.c)

Clemens L. schrieb:
>Die Timer sind unabhängig.
>Aber du hast nur eine CPU, und kannst nur einen Interrupt-Handler auf
>einmal ausführen.
Nach diesen Hinweisen  scheint es mir, dass das so nicht funktionieren 
wird.
Noch einmal die Frage, ob es eine andere Lösungsidee gibt.

von Jürgen W. (Firma: MED-EL GmbH) (wissenwasserj)


Lesenswert?

1. Du hast bei der ISR von Tmr A außerdem vergessen das CCIFG zu löschen 
- wird also ständig aufgerufen.
2. Warum baust Du ZeitOB_A und ZeitUB_A, statt einen einzigen 
short-Variable? Macht ja alles nur kompliziert.

von Clemens L. (c_l)


Lesenswert?

Jürgen W. schrieb:
> Du hast bei der ISR von Tmr A außerdem vergessen das CCIFG zu löschen

Nein, das Flag für TIMERA0_VECTOR wird automatisch zurückgesetzt.

wolle g. schrieb:
> Nach diesen Hinweisen  scheint es mir, dass das so nicht funktionieren
> wird.

Du solltest in beiden Interrupthandlern so wenig Arbeit wie möglich 
machen, d.h., nur ein Flag setzen (und den Zeitstempel lesen), und dann 
in der Hauptschleife in main() prüfen, ob etwas zu tun ist.

von Peter D. (peda)


Lesenswert?

Clemens L. schrieb:
> Wenn ein Handler schon ausgeführt wird, wird er nicht mehr
> unterbrochen.

Dieses Problem kannte ich bisher nur von den AVRs. Selbst die alten PIC 
und 8051 hatten schon 2..4 Interruptlevel.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Dieses Problem

... existiert in dieser Form ja auch nicht, wie ich schon beschrieb. In 
der ISR kann das Interruptflag wieder freigegeben werden, danach kann 
dann der nächste Interrupt die noch laufende ISR unterbrechen. 
Allerdings wird in diesem Fall die Priorität der laufenden ISR nicht 
berücksichtigt, d.h. sie kann dann auch von einem Interrupt niederer 
Priorität unterbrochen werden.

Die Prioritäten werden nur bei gleichzeitig auftretenden Interrupts 
ausgewertet, nicht bei nacheinander auftretenden.

Hier http://www.simplyembedded.org/tutorials/msp430-interrupts/ findet 
sich ein das ganze beschreibender Text.

von Nutze die gute TI Doku! (Gast)


Lesenswert?

RTFM (aus FUG):
... Interrupt priorities determine what
interrupt is taken when more than one interrupt is pending 
simultaneously. ...

... Interrupt nesting is enabled if the GIE bit is set inside an 
interrupt service
routine. When interrupt nesting is enabled, any interrupt occurring 
during an
interrupt service routine will interrupt the routine, regardless of the 
interrupt
priorities. ...

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.