Überlauf bei int32_t trotz Satuierungsversuch?

OP #2307989
Lesenswert?

Hallo,

ich habe hier Probleme mit einem Codeschnipsel (für einen ATmega644P @ 
16MHz).
Damit ihr euch einen Überblick verschaffen könnt, was der Schnipsel 
bewirken soll, erstmal eine kurze Erläuterung.


Ich möchte mehrere 8-Bit Werte (effektiv) innerhalb einer beliebigen, 
durch den Wert von fadeFaktor bestimmten Zeit ansteigen oder absinken 
lassen, bis ein Zielwert erreicht ist.
Da der Codeschnippsel ~ mit 100Hz aufgerufen wird und auch Zeiten > 2,55 
Sekunden möglich sein sollen, führe ich die Berechnung mit 16-Bit Werten 
durch, von denen im weiteren Programmverlauf (siehe unten im Code) dann 
jeweils nur die oberen 8-bit verwendet werden (daher effektiv 8-bit) - 
die unteren dienen dazu, den Ablauf zeitlich strecken zu können.

Die 8-bit Zielwerte sind in PresetTargetValues[] gespeichert, die 16-bit 
Berechnungswerte in PresetValues.

Da der Zielwert nicht überschritten werden soll berechne ich zunächst in 
einem int32_t und entscheide dann a posterori, ob der Zielwert erreicht 
ist (und setze diesen) oder benutze den berechneten Wert. Ein Überlauf 
sollte daher ja eigentlich nicht auftreten.

Trotzdem kommt es dann (und nur dann) wenn der Zielwert 255 ist und eine 
nicht natürliche Anzahl von Berechnungen notwendig ist um den Zielwert 
zu erreichen zu einem Überlauf - zumindest springt der Wert in 
PresetValues auf 0 zurück und bleibt nicht beim oberen Zielwert 255, 
sodass sich der Vorgang (mehrfach) wiederholt.


Ich habe jetzt mehrfach drübergeschaut und versucht einen Fehler zu 
finden, bin aber bisher ratlos geblieben. Liegts am großen int32_t oder 
habe ich ein Brett vorm Kopf?


Würde mich freuen, wenn ihr Rat wüsstet.

LG :)

(Dass dies nicht unbedingt der effizienteste Weg ist ist mir bewusst, 
soll aber nicht weiter Thema sein)
1
uint16_t fadeFaktor;
2

3
  // ...
4

5
uint8_t i;
6
int32_t tmp; // signed 32bit !!
7
for(i=0; i<CHANNEL_TO_TX; i++){
8
  
9
  if(PresetTargetValues[i] > ((uint8_t)(PresetValues[i] >> 8))){
10
    
11
    tmp = PresetValues[i] + fadeFaktor;
12
    
13
    if(tmp > ((uint16_t)(PresetTargetValues[i] << 8))){
14
      
15
      PresetValues[i] = (uint16_t) PresetTargetValues[i] << 8);
16
      
17
    }
18
    else{
19
      
20
      PresetValues[i] = (uint16_t) (tmp & 0xFFFF);
21
      
22
    }
23
    
24
  }
25
  else if(PresetTargetValues[i] < ((uint8_t)(PresetValues[i] >> 8))){
26
      
27
    tmp = PresetValues[i] - fadeFaktor;
28
      
29
    if(tmp < ((uint16_t)(PresetTargetValues[i] << 8))){
30
        
31
      PresetValues[i] = (uint16_t) (PresetTargetValues[i] << 8);
32
        
33
    }
34
    else{
35
        
36
      PresetValues[i] = (uint16_t) (tmp & 0xFFFF);
37
        
38
    }
39
      
40
  }
41
    
42
  DmxTx.values[i] = (uint8_t) (( ( (uint8_t)(PresetValues[i] >> 8) ) * masterChannel ) / 255);
43
    
44
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren