Forum: Mikrocontroller und Digitale Elektronik Differenz zwischen "übergelaufenen" Werten


von ArduStemmi (Gast)


Lesenswert?

Ich stehe im Moment mächtig auf dem Schlauch!
Ich möchte gern eine eigene Zeitmessung im Programm umsetzen. Alle Timer 
haben schon Ihre Aufgaben abbekommen (4 x PWM in Timer0 und Timer2, 
Timer1 Overflow Interrupt soll PWM-Values aktualisieren). Aus diesem 
Grund möchte ich TCNT1 benutzen um Zeitdifferenzen zu ermitteln. Da es 
zum Überlauf kommen kann, mache ich folgendes:
1
uint16_t My_Time_Dif(uint16_t cnt)  // Hier wird TCNT1 eingetragen
2
{
3
  static uint32_t lastTime;   // letzter Zeitstempel in meiner 
4
                                    // Zeitrechnung
5
  uint32_t now;
6
  uint32_t dif;
7
  
8
  now = cnt;
9
  
10
  if (now < lastTime)
11
  {
12
    now += 65536;
13
  }
14
  
15
  dif =  now - lastTime;
16
  
17
  lastTime = cnt;
18
  
19
  return (uint16_t) dif
20
}
und habe dabei ein komplett schlechtes Gewissen. Dieses rumhantieren mit 
16bit und 32bit Zahlen gefällt mir überhaupt nicht. Ich bin sicher das 
es viel einfacher geht.
Meine eigenen Berechnungen auf dem Zettel haben aber immer Mist ergeben, 
hat jemand eine Idee?

von Max H. (hartl192)


Lesenswert?

Wenn der 16bit-Timer in der Zwischenzeit nur einmal überläuft, machst 
du keinen Fehler, wenn du nur mit 16bit rechnest und den überlauf 
einfach ignorierst.

von ArduStemmi (Gast)


Lesenswert?

also einfach:
1
(uint16_t) dif = (uint16_t) now - (uint16_t) lasttime;

Ich hab' genau das mit der Hand gerechnet und komme eben nicht drauf! 
Warum ist das so?

von Wolfgang A. (Gast)


Lesenswert?

ArduStemmi schrieb:
> Ich hab' genau das mit der Hand gerechnet und komme eben nicht drauf!
> Warum ist das so?

Weil die Spiel-/Rechenregeln für uint so sind.

von Max H. (hartl192)


Lesenswert?

ArduStemmi schrieb:
> (uint16_t) dif = (uint16_t) now - (uint16_t) lasttime;
Wenn du lastTime, now und dif als uint16_t deklarierst kannst du dir die 
ganzen Casts sparen.

> Ich hab' genau das mit der Hand gerechnet und komme eben nicht drauf!
> Warum ist das so?

Beispiel mit 3bit:

1)
Wert alt: 001 = 1d
Wert neu: 011 = 3d

-alt: 110 + 1 = 111 = -1d   // 2er-Komplement

neu + (-alt):
 011 +
 111
 ---
1010 = 2d   // Überlauf wird gelöscht, da nur 3bit Zahl


2)
Wert alt: 110 = 6d
Wert neu: 000 = 0d

-alt: 001 + 1 = 010 = -1d   // 2er-Komplement

neu + (-alt):
 000 +
 010
 ---
0010 = 2d

Der Timer hat bei beiden Beispielen um 2 weitergezahlt, das Ergebnis der 
Subtraktion bleibt das gleiche, da der Überlauf nicht berücksichtigt 
wird, da man konsequent nur mit 3bit Zahlen arbeitet.
Analog für 16bit, ich wollte mir aber etwas Schreibarbeit sparen.

von W.A. (Gast)


Lesenswert?

ArduStemmi schrieb:
> Ich hab' genau das mit der Hand gerechnet und komme eben nicht drauf!

Dann hast du vermutlich die Rechenregeln für uint16 nicht vollständig 
berücksichtigt. Wenn du allerdings deinen Rechenweg auf ewig für dich 
behälst, wird dir auch keiner sagen können, was da schief gelaufen ist.

von ArduStemmi (Gast)


Lesenswert?

Herzlichen Dank! Dann habe ich mich auf meinem Zettel wohl verrechnet! 
Obwohl ich, wie Du, auch bloß mit 3bit gerechnet habe.

Ich glaube, man sollte nicht soviel arbeiten, zwischen den Wochenenden, 
das erschöpft und lenkt von den wichtigen Bits und Bytes ab!

Herzlichen Dank nochmal!

PS: Ich werde meinen Zettel nicht einscannen und hier posten, war ja eh 
falsch!

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.