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 | }
|