mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: wolle g. (wolleg)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: isr_checker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
villeicht sind deine Routinen in den ISRs zu lang

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

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: wolle g. (wolleg)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Autor: isr-checker (Gast)
Datum:

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

Die Timer sind unabhängig voneinander.

Autor: Clemens L. (c_l)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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.

Autor: wolle g. (wolleg)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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.

Autor: Clemens L. (c_l)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nutze die gute TI Doku! (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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. ...

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.