Zurück (C) Christof Ermer, Regensburg

15.12.2010


Was passiert wenn ein Byte hochgezählt wird, und dann die Variable  überläuft.?? ( bei Minusvergleichen )


Problem ich möchte wissen, wieviel  Zeit seit einem Ereigniss vergangen ist.

1. Ich habe einen Zeit-Zähler, der immer  größer wird       TICK-Counter genannt.. Also wie eine Takt-Uhr...
Wirklich "IMMER" ???  

 Das geschieht automatisch in einer Timer gersteuerten Routine ( ISR  )  und einer Variable  gu32_Ticks++;
// ***************************
SIGNAL(TIMER2_OVF_vect)
// ***************************
{sei();  gu32_Tick++; };

Wir arbeiten ja mit Variablen als Datentypen, und auch der Größte Datentyp hat ein Enden
unsignet char    0..255  
unsignet int    0..65535
unsignet long    0..4294967295
und die integer Variablen sind Bereich (so etwa in die Mite), aber dann Plus/Minus.
signed char -127..+128
oder 65536 / 2 = -32767 ..+32768   usw.  
Grund:
Bei signet Datentypen wird das letzte Bit ( MSB= Most Signifikant Bit ) als Vorzeichen hergenommen
 0=+, 1=-    dann kommen die Daten( deshalb kan nur die Hälfte der Wer Datentypbreite dargestellt werden
(+/- )XXX XXXX   x=Datenbits

Zurück zum Problem:
Zum vergleichen, ob eine gewisse Zeit vergangen ist,  muss mann sich vorher die Ereignisszeit merken.
1.)    u32TimeCompare = gu32_Ticks;  //MERKEN   

DANN!!  kann man so oft wie möglichen nachsehen, ob dies der Fall ist. ( klassisch im Main-Loop )
if ( (gu32_Ticks - u32TimeCompare) > WARTEZEITTICKS )
    {  
    u32TimeCompare = gu32_Ticks;  ///merke Dir wieder die neue EventZeit
   // Und nun tue was du tun wolltest.... z.B. Strom nach 5 Sekunden abschalten................
    };

FRAGE , Was passiert, wenn die Zählvariable überläuft ??
Also die uint32_t TicksVariable kann "NUR" bis 4294967295 Zählen

BSP: 16 Mhz Quarz / 256 Vorteiler / 256  = 244.140625  = ~ 244 Ticks / Sekunde
2^32 (uint32_t) =  4294967296  / 244 =  17602325  Sekunden
/60  = 293372 Minuten
/60 = 4890 Stunden
/24 = 203 Tage    
Nach 203 Tagen läuft der TICK-Zähler über!!! WAS DANN ? ( Damit soll man nicht leben müssen)

Dann wird aus einer sehr großen Variable eine sehr kleine...!
4294967293 ----  4294967294 ----  4294967295 ---- 0 ----1---- 2---- 3 ----
aber der letzte Merkwert ( u32TimeCompare) war sehr groß 

Problem:
 KLEINE Zahl  MINUS GROSSE Zahl  =  Minuswert

Für einen Größer Vergleich Unbrauchbar....
Wir würden EWIG warten, bis die Bedingung erfüllt ist.  so etwa 203 Tage !!! Das ist quatsch.

Die LÖSUNG IST GANZ EINFACH...
 Groß MINUS Klein erzeugt  einen "signet Datenyp" als Rückgabewert...
Minus können wir nicht brauchen:
TRICK: einfach einen (TYPECAST) auf unsigned durchführen und diesen (unsigned type ) zurückgeben.
Das MSB-Signed Bit (1) wird einfach als Datenwert interpretiert.  Folge: Das Ergebnis stimmt wieder.

((uint8_t)(uKlein - uGross)) = richtiger Wert;   Beachte den Typecast auf unsigned, nach der Subratktion
  0 - 3 ist nicht -3 sondern (unit8_t)( 0 - 3) = 253 bei einem uint8_t Datentyp

//Funktion zur automatisch richten Vergleichs-Differenz Prüfung
// ***********************************
uint32_t GetTickDifference(uint32_t u32Time)
// ***********************************
{
return (gu32_Ticks - u32Time);  //Typecast auf unsigned --- evtl. Minusergebnisse gibt PLUS
};


Beweis: Bytevariable hochzählen
253  hochzählend
250   Differenzergebniss zu  -3

254 hochzählend
251 Differenzergebniss zu  -3

255 hochzählend  ( letztes Bit im Byte )
252 Differenzergebniss zu  -3

0   hochzählend  Überlauf Punkt
253 Differenzergebniss zu  -3;  Ergebniss STIMMT:  (unsigned)0 - 3 = 253

1  hochzählend
254 Differenzergebniss zu  -3

2  hochzählend
255 Differenzergebniss zu  -3

250 hochzählend
247 Differenzergebniss zu  -3