Not logged in. · Lost password · Register

heinloth
heinloth
Member since Jul 2017
8 posts
Subject: Überlauf bei Wartefunktion
Für die neue Aufgabe Snake ist es in Schritt 3 notwendig, abhängig von der Helligkeit eine Wartefunktion zu implementieren.

Unter Umständen hat man für die Wartezeit eine Funktion ähnlich
Initialwert - Faktor * ADC(PHOTO)

Hier gibt es einen Stolperstein, welcher in der Vorlesung am Montag auf Folie 7-15f erörtert wurde.

Beispiel:
Nehmen wir für den ADC-Wert des Photosensors 1000 an und setzen den Faktor auf 2000 und die Wartezeit auf 3000000 (Hinweis: das sind fiktive Werte, welche nicht so in der Aufgabe benutzt werden).
Auf dem Papier ist es einfach:
3000000 - 2000 * 1000 = 1000000

Und nun als kleine Testanwendung, welche die gleiche Rechnung tätigt und dann beim erwarteten Ergebnis die grüne LED anknippst:
  1. #include <stdint.h>
  2. #include <led.h>
  3.  
  4. void main(void){
  5.     uint16_t adc = 1000; // eigentlich sb_adc_read
  6.     uint32_t delay = 3000000 - 2000 * adc;
  7.  
  8.     switch (delay){
  9.         case 1000000:
  10.             sb_led_on(GREEN0);
  11.             break;
  12.         case 2966080:
  13.             sb_led_on(YELLOW0);
  14.             break;
  15.         default:
  16.             sb_led_on(RED0);
  17.     }
  18.  
  19.     while (1);
  20. }

Allerdings leuchtet beim Ausführen auf dem SPiCboard die gelbe LED und sagt uns damit, dass das Ergebnis 2966080 ist. Wieso?

Zuerst gilt bei der Formel 3000000 - 2000 * adc Punkt vor Strich. Und 2000 ist wie die Variable adc eine 16bit Zahl. Das Ergebnis wird wieder in 16bit gepackt und die führenden Stellen werden abgeschnitten, es gibt einen Überlauf:
            0000 0111 1101 0000₂    (= 2000₁₀)
*           0000 0011 1110 1000₂    (= 1000₁₀)
----------------------------------------------
= 0001 1110 1000 0100 1000 0000₂ (= 2000000₁₀)
→ ▒▒▒▒ ▒▒▒▒ 1000 0100 1000 0000₂   (= 33920₁₀)

Anschließend wird das Ergebnis von 3000000 (aufgrund der Größe bereits 32bit) abgezogen, wir erhalten statt 1000000 die ungewünschte Zahl 2966080.

Als Lösung muss man nun entweder bereits adc zum Typ uint32_t machen, casten ((uint32_t) adc) -- oder den Übersetzer anweisen, den anderen beteiligten Operanden als 32bit Zahl zu behandeln: 2000UL.


Tückische Sache - wieso nerven wir euch mit solchen Problem? Nun, derartige Überlauffehler haben schon teure Raketen zum explodieren gebracht - und wir machen natürlich Rocket Science in GSPiC ;)
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O :troll:
Special characters:
Go to forum
Powered by the Unclassified NewsBoard software, 20110527-dev, © 2003-8 by Yves Goergen