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
villeicht sind deine Routinen in den ISRs zu lang
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
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?
>Ich hatte gedacht, jeder Timer arbeitet separat und hatte deshalb extra >zwei Timer verwendet. (Irtum) Die Timer sind unabhängig voneinander.
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.
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.
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.
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.
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.
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.