www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit Dividieren in C für AVR


Autor: oles (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: oles (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: oles (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.