Hallo, gerade programmiere ich zum ersten Mal einen Atmel AVR in C, da ich bei meinen aktuellen Projekt viele arithmetische Operationen mit großen Zahlen durchführen muss. Nur passiert dabei nicht so ganz das was ich möchte: Um die Geschwindigkeit eines Fahrrads zu bestimmen, messe ich die Zeit, die ein Rad-Umlauf benötigt. Dazu lasse ich Timer0 mit einem Vorteiler von 256 laufen und zähle bei jedem Überlauf dieses Timers eine extra Variable hoch: uint8_t volatile TimerHigh; ISR(TIMER0_OVF_vect) { if(TimerHigh!=0xFF) { TimerHigh++; } } Ist nun ein Rad-Umaluf beendet, wird folgende Berechnung ausgeführt: uint32_t KMHTemp; KMHTemp = (TimerHigh<<14); KMHTemp |= (TCNT0<<6); KMHTemp++; KMHTemp = 7200000/KMHTemp; // 7200000 = 2000000 um * 3,6 KMHTemp soll zunächst die Umlaufdauer in usec enthalten. Dazu: Der Controller ist mit 4 MHz getaktet. TimerHigh:TCNT0:Prescaler repräsentiert die Zahl der "Takt-Ticks" (mir fällt gerade nicht das richtige Wort dafür ein), die ein Radumlauf gebraucht hat. Den Prescaler ignoriere ich einfach. Also ist der gesuchte Wert genähert (TimerHigh:TCNT0)*256. Ein "Takt-Tick" dauert bei 4 MHz 0,25 usec. Also ist die gesuchte Dauer in usec etwa (TimerHigh:TCNT0)*256/4 = (TimerHigh:TCNT0)*64 "= (TimerHigh:TCNT0) << 6". Damit KMHTemp nie 0 ist, erhöhe ich es um 1. Um jetzt die Geschwindigkeit in km/h zu errechnen teile 2 m * 3,6 = 2000000 um * 3,6 = 7200000 durch KMHTemp. Nun ist das Ergebnis dieser Rechnung seltsamerweise praktisch immer 0. Setze ich im Simulator (AVR-Studio) TimerHigh und TCNT0 auf solche Werte (0x2B und 0xF2), sodass sich nach Mulitplikation mit 64 und Addition von 1 der Wert 720001 ergeben sollte, erhalte ich an Stelle von 10 (oder von mir aus auch 9, ich weiß nicht, wie er rundet) das Ergebnis 0. Hat jemand eine Idee, woran das liegen könnte? Ich benutze WinAVR-20090313. Beste Grüße Ole
oles wrote:
> KMHTemp = (TimerHigh<<14);
Kannst ja mal selbst überlegen, was passiert, wenn man einen 8-Bit-Wert
um 14 Stellen nach links schiebt. Und bevor die üblichen Zweifel kommen:
Nein, es ist völlig egal, welcher Datentyp links vom "=" steht. die
Zuweisung wird als letztes gemacht. Selbst wenn der Compiler die
Berechnung in int durchführt, bleibt nicht viel übrig.
Ah, gut, das war mir nicht klar. Also dürfte es Abhilfe schaffen, erst mal alles in 32 bzw. 16 Bit breite ints zu schieben und dann erst die Zusammensetzung zum endgültigen 32 bit Wert vorzunehmen?
Ah verdammt Schnellschuss... So sollte es auch ohne Zwischenspeichern gehen: KMHTemp = TimerHigh; KMHTemp = KMHTemp << 8; KMHTemp |= TCNT0; KMHTemp = KMHTemp << 6; KMHTemp++; KMHTemp = 7200000/KMHTemp; Vielen Dank Johannes!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.