mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 - Timer Interrupt zu früh


Autor: dk (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Bei der Programmierung meines Controllers für die Ansteuerung von 
Thyristoren bin ich auf ein Problem mit meinem Timer gestoßen. Mein 
genutztes System:

-MSP430FG4618
-32kHz Quarz für ACLK
-IAR Embedded Workbench Version 5.10.1
-Programmierung in C

Zur besseren Fehlersuche habe ich mein Programm möglichst weit gekürzt. 
Da ich quasi keine Erfahrung mit C habe und es sich um mein erstes 
Projekt mit einem Mikrocontroller handelt, hoffe ich das nicht zuviele 
grundsätzliche Fehler vorhanden sind.

Was im Programm eigentlich passieren soll:
An Pin 0 von Port 1 ist das Ausgangssignal eines Schmitt-Triggers 
angeschlossen, dieser liefert mir alle 20ms eine steigende Flanke. Der 
durch die Flanke ausgelöste Interrupt testet von welchem Pin der 
Interrupt kommt (später sollen 3 Schmitt-Trigger angeschlossen werden) 
und legt dann in den Variablen thyristorA1 und thyristorA2 ab welche 
Ausgangspins später auf High gesetzt werden sollen. Danach wird TimerA 
im up-mode gestartet. TACCR0 wird auf einen Wert in Abhängigkeit von 
alpha gesetzt. In dem Programm im Anhang ist alpha zwar konstant, im 
ungekürzten Programm wird es aber verändert..
Im Timer Interrupt werden dann die Pins an Port 4 entsprechend 
thyrsitorA1 auf High gesetzt und der Timer wieder gestartet, diesmal mit 
TACCR0 = alphaT[2]; was TACCR0 = 560 entsprechen sollte. Beim zweiten 
Timer Interrupt werden die Pins von Port 4 wieder auf Low gesetzt und 
der Timer mit einem größeren Überlaufwert TACCR0 = alphaT[10]; 
(TACCR0=2778) gestartet. Der dritte Timer Interrupt setzt die Pins 
entsprechend thyristorA2 auf High und startet den Timer mit TACCR0 = 
560. Beim letzten Timer Interrupt werden die Pins wieder auf Low gesetzt 
und der Timer nicht wieder gestartet.
Dieser Teil des Programms funktioniert soweit auch (falls man den Basic 
Timer nicht starten würde). Wenn jetzt zusätzlich noch der Basictimer 
genutzt wird, auch wenn er nur eine Varible hochzählt die mit dem Rest 
nichts zu tun hat, kommt es zu Problemen. Wenn ich mir das Signal der 
Ausgangspins auf dem Oszi anschaue, ist manchmal alles wie es sein soll, 
manchmal werden die Pins aber auch im falschen Moment auf High gesetzt. 
Die beiden Fälle in denen der Timer nur bis TACCR0 = alphaT[10] laufen 
soll sind in Ordnung, aber wenn der Timer Interrupt erst bei dem höheren 
Wert TACCR0 = alphaT[10] kommen sollte, wird direkt die ISR aufgerufen. 
D.h. die Phase zwischen den Zeitabschnitten in denen die Pins auf High 
liegen ist fast nicht mehr vorhanden.

Ich glaube ich habe irgendetwas grundsätzliches bei der Nutzung von 
mehreren Interruptquellen falsch gemacht und wäre froh über jeden Tipp!
Im Moment sind alle Variablen als volatile deklariert, wobei ich 
eigentlich dachte es wäre nicht bei allen nötig...dadurch tritt der 
Fehler aber seltener auf. Wenn ich das Programm Schritt für Schritt 
debugge funktiert es wie es soll. Soweit ich den Assembler Code (habe so 
gut wie garkeine Ahnung von Assembler) nachvollziehen kann, konnte ich 
auch keinen Fehler finden....

Danke schonmal für alle Antworten!
Gruß

Autor: dk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal!
Ich konnte den oben beschriebenen Fehler noch weiter einschränken, wenn 
ich in dem Programm im ersten Beitrag in:
[c]
#pragma vector = BASICTIMER_VECTOR
__interrupt void BASICTIMER_ISR (void)
{
 uint16_t bt = btcounter;
 if ( bt == 20 )
  {
    bt = 0;
  }
 btcounter = ++bt;
}
[\c]
die Variable "bt" ebenfalls als volatile deklariere tritt der Fehler 
nicht auf, oder zumindest so selten, dass ich ihn nach mehreren Minuten 
nicht mehr am Oszi beobachten konnte. Leider verstehe ich nicht warum es 
so ist, da der Fehler ja bei TimerA auftritt und nicht beim Basic Timer.
Der Assembler Code den der Compiler ausspuckt unterscheidet sich 
dementsprechend auch nur minimal:

Funktioniert nicht:
BASICTIMER_ISR:
?cstart_end:
 003128    120F               push.w  R15
  /*volatile*/ uint16_t bt = btcounter;
 00312A    421F 110C          mov.w   &btcounter,R15
  if ( bt == 20 )
 00312E    903F 0014          cmp.w   #0x14,R15
 003132    2001               jne     0x3136
    bt = 0;                          
 003134    430F               clr.w   R15
 btcounter = ++bt;                             
 003136    531F               inc.w   R15
 003138    4F82 110C          mov.w   R15,&btcounter
}
 00313C    413F               pop.w   R15
 00313E    1300               reti
__interrupt void P1_ISR (void)
{

Funktioniert:
BASICTIMER_ISR:
?cstart_end:
 003128    120F               push.w  R15
 00312A    8321               decd.w  SP
  volatile uint16_t bt = btcounter;
 00312C    4291 110C 0000     mov.w   &btcounter,0x0(SP)
  if ( bt == 20 )
 003132    90B1 0014 0000     cmp.w   #0x14,0x0(SP)
 003138    2002               jne     0x313E
    bt = 0;                          
 00313A    4381 0000          clr.w   0x0(SP)
 btcounter = ++bt;                             
 00313E    412F               mov.w   @SP,R15
 003140    531F               inc.w   R15
 003142    4F81 0000          mov.w   R15,0x0(SP)
 003146    4F82 110C          mov.w   R15,&btcounter
}
 00314A    5321               incd.w  SP
 00314C    413F               pop.w   R15
 00314E    1300               reti

Kann mir jemand erklären wieso diese lokale Variable im Interrupt des 
Basictimers meinen TimerA beeinflussen kann?
Gruß

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.