Forum: Mikrocontroller und Digitale Elektronik Timerüberlauf für Periodenauswertung läuft falsch


von Em G. (exe87)


Angehängte Dateien:

Lesenswert?

Guten Morgen zusammen.
Ich hab ein Problem mit einer Periodenauswertung über einen TimerA
Hier mal der Code:
1
#include <msp430G2153.h>
2
3
#define Sleep 15000
4
5
volatile unsigned int stop, start;
6
volatile unsigned int Periode;
7
volatile unsigned int SignalChange=0;
8
volatile int bla=0;
9
10
11
//----ISR for Signalchange----
12
#pragma vector=PORT1_VECTOR
13
__interrupt void Port_1(void)
14
{
15
  stop=TAR;                            //Aktuellen Timerwert in stop schreiben
16
  SignalChange++;                          //Flankenwechsel
17
18
  if(TACTL & TAIFG)
19
    bla=1;
20
  else
21
    bla=0;
22
23
  //Periode Calculation
24
  if(!(TACTL & TAIFG)){
25
    Periode=stop-start;                      //Periode ausrechnen
26
  }
27
  else{
28
    if(TACTL & TAIFG){
29
      if(stop<start)
30
        Periode=(65535-(start-stop));
31
      if(stop>start)
32
        Periode=15001;
33
    }
34
  }                          //naechste Messung vorbereiten
35
  if(SignalChange<15 && Periode>=Sleep)
36
    _NOP();
37
  start=stop;
38
}

Also:
Er soll sich in "stop" den Wert aus TAR laden.
bla ist nur eine Hilfsvariable.
Wenn kein Überlauf stattgefunden hat, soll er ganz normal ausrechnen, 
ansonsten die anderen beiden Berechnungen durchführen.
der nächste Schritt war nur zur Überprüfung eines Fehlers.

Es können ja 3 Zustände bei der Berechnung auftreten:
1. Der Timer läuft ganz normal hoch und währenddessen soll die Zeit 
gemessen werden: zB stop=60000 und start war 10000 Differenz: 50000
2. Der Timer hatte einen Überlauf und stop ist größer als start, also:
stop=60000 und start war 10000, Differenz: 115535
3. Der Timer hatte einen Überlauf und stop ist kleiner als start, also: 
stop=10000 und start war 60000, Differenz: 15535

Normalerweise kann während der 15 Signalwechsel die Zeit nie größer sein 
als ca. 10000. Trotzdem springt er manchmal in die Berechnung rein, wo 
stop>start ist UND ein Überlauf stattgefunden haben soll.
1
      if(stop>start)
2
        Periode=15001;
Wenn ich aber die Hilfsvariable "bla" angucke, steht dort eine 0, welche 
ja normalerweise auf 1 sein müsste.
Also es wird quasi eine große Periodendauer gemessen, die eigentlich 
nicht sein darf.

Da der MSP430G2153 nur 16Bit hat, habe ich für Fall 2 einfach einen 
festen Wert genommen.

von Em G. (exe87)


Angehängte Dateien:

Lesenswert?

Also ich hab nochmal genau geguckt, diese Fehleranalyse tritt wohl nur 
auf, wenn der Timerüberlauf während der ISR auftritt.
Was kann man dann tun?
Weil so eine Art Prioritätenänderung der Interrupts gibt es laut 
Datenblatt nicht :(

LG

von Karl H. (kbuchegg)


Lesenswert?

Em Gr schrieb:
> Also ich hab nochmal genau geguckt, diese Fehleranalyse tritt wohl nur
> auf, wenn der Timerüberlauf während der ISR auftritt.
> Was kann man dann tun?

Möglichst zeitnah Zählerwert und Überlaufflag auslesen. Und zwar nur 
einmal!
Und nicht so wie du quer über die ganz ISR verstreut immer wieder das 
Hardware-Flag checken.

Zusätzlich könntest du noch, wenn du bei der Reihenfolge
   Zähler auslesen
   Überlauf feststellen
bleibst:

wenn der Zählerwert an der oberen Grenze ist (65535) UND das 
Überlaufflag trotzdem gesetzt ist, dann könntest du die Messung 
verwerfen, weil du nicht sicher sein kannst, ob nicht das Überlaufflag 
zwischen den beiden Auslesevorgängen gesetzt wurde, oder ob es nicht 
tatsächlich vorher schon gesetzt war.


Wo setzt du eigentlich das Überlaufflag zurück?
Oder geschieht das automatisch mit dem Auslesen?


PS: wenn du sicher weißt, dass deine Differenz nie größer als 10000 sein 
kann, dann brauchst du auch das Überlaufflag nicht.
Rechne einfach stop - start und durch die unsigned Rechnung kommt auch 
dann das richtige Ergebnis raus. Da brauchst du nicht künstlich sowas
       Periode=(65535-(start-stop));
rechnen lassen.

Die einfache Subtraktion geht erst dann schief, wenn die absolute 
Differenz tatsächlich größer als 65535 ist, also mehr als 65535 
Timerticks gezählt werden müssen.

von Em G. (exe87)


Angehängte Dateien:

Lesenswert?

Super, es läuft nun richtig, hatte wohl etwas mit der Mehrfachabfrage zu 
tun.
1
#include <msp430G2153.h>
2
3
#define Sleep 15000
4
5
volatile unsigned int stop, start;
6
volatile unsigned int Periode, Help=0;
7
volatile unsigned int SignalChange=0;
8
volatile int bla=0;
9
volatile unsigned int OverflowCounter=0;
10
11
12
#pragma vector=TIMER0_A1_VECTOR      //TIMER0_A1_VECTOR
13
__interrupt void Timer_A(void){
14
  OverflowCounter++;
15
  TACTL &= ~TAIFG;          //TimerA Interrupt Flag loeschen
16
  P1OUT ^= BIT0;
17
}
18
19
//----ISR for Signalchange----
20
#pragma vector=PORT1_VECTOR
21
__interrupt void Port_1(void)
22
{
23
  stop=TAR;                            //Aktuellen Timerwert in stop schreiben
24
  Help=OverflowCounter;
25
  Periode=stop-start;
26
  if(Help>=1){
27
    if(stop<start)
28
      Periode=stop-start;
29
    if(Help>1 || stop>start)
30
      Periode=25001;
31
32
  }
33
  SignalChange++; 
34
  OverflowCounter=0;
35
  TACTL &=~ TAIFG;
36
}

Jedoch frage ich mich noch, wie es sein kann, dass der Timer in der 
Ruhephase nicht Regelmäßig läuft: rote Kreise(Habe testweise jeden 
Überlauf anzeigen lassen). Normalerweise müsste er doch wie in den 
weissen Kreisen sein.

von Peter D. (peda)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Möglichst zeitnah Zählerwert und Überlaufflag auslesen.

Das macht den Fehler nur seltener, beseitigt ihn aber nicht.
Eine garantiert fehlerfreie Auslesung macht man z.B. so:

Beitrag "AVR Timer mit 32 Bit"


Peter

von Em G. (exe87)


Angehängte Dateien:

Lesenswert?

Also die Signalauswertung funktioniert nun tadellos, vielen Dank!!

Aus dem ausgewerteten Signal sollen 4 PWMs erzeugt werden, welche auch 
genauso funktionieren, wie sie sollen, bis auf kleine Aussetzer(roter 
kreis) der PWM.
Diese führen dazu, das es "flackert".
Könnte dies an dem Timer liegen?

Prinzip:
Über das TAR wird die Zeit ausgelesen, und die Perioden ermittelt, 
daraus resultiert 1 oder 0. Diese ergeben die Dimmwerte.
Über TA0.1, TA0.2, TA1.1 und TA1.2 werden 4 PWMs erzeugt.

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.