AVR: Effizienzter weg gesucht um Hertz in Mehahertz umzurechen

Gast #1048683
Hallo,

Ich baue mir gerade einen Frequenzzähler und habe den Wert der Frequenz 
in Hertz in einer Variablen:

unsigned long int hertz=123456789; // Zum beispiel ;)

So nun stellt sich mir die Frage wie ich es am besten in Mhz auf dem 
display darstelle.

AVR sind ja nicht für Flieskomma-Arithmetik ausgelegt und deswegen würde 
hertz/1000000 erstens ewig dauern, und zweitens würde sprintf mit 
Flieskommazahlen auch ewig brauchen.

Gibt es eine schnelle vernünftige Lösung um nicht unnötig komplexe 
Flieskommaoperationen durchzuführen nur um den Wert darzustellen?
Gast
>AVR sind ja nicht für Flieskomma-Arithmetik ausgelegt und deswegen würde
>hertz/1000000 erstens ewig dauern, und zweitens würde sprintf mit
>Flieskommazahlen auch ewig brauchen.

Was ist bei dir ewig? Eine Ausgabe auf LCD braucht länger
als die Umrechnung mit float und Stringwandlung mit sprintf.

Was bitte schön dauert da zu lange?
Cagara wrote:

> AVR sind ja nicht für Flieskomma-Arithmetik ausgelegt und deswegen würde
> hertz/1000000 erstens ewig dauern,

Hängt ein bischen davon ab, was für dirch "ewig" ist.

> und zweitens würde sprintf mit
> Flieskommazahlen auch ewig brauchen.

Wetten dass der Controller schneller rechnet als du auf's Display gucken 
kannst?

Ist aber nicht nötig. Nimm itoa/sprintf mit integer und verwurste den 
erzeugten String entsprechend.
Gast
Die Frage ist auch, ob man sich den Wert tausend mal pro sekunde neu 
berechnen lassen soll, oder ob 5 mal allenfalls genuegen wuerde. Oder 
auch nur ein mal pro sekunde.
Gast
Hallo,

ich sehe weder bei

unsigned long int hertz=123456789;

noch bei

hertz/1000000;

die Notwendigkeit, eine wie auch immer geartete FP-Engine anzuwerfen.
ist doch alles Ganzzahlarithmetik (wenigstens so, wie es da steht).

im Ernst: einfach wie Benedikt bereits schrieb den Dezimaltrenner an der
gewünschten Stelle einfügen, überflüssige Stellen einfach vorher 
abtrennen.

ciao

Marcus
Gast
Okay vielen lieben dank an euch alle :)
Habt mir sehr die Augen geöffnet ...

Habe mir jetzt soetwas hier geschrieben und es funktioniert prima ...

Sieht nicht schön aus, aber tut hoffentlich effizient seinen Job!

Für alle Anfänger die später noch davon profitieren möchten ... hier der 
Code :) Ich sage extra "Anfänger" weil die eingefleischten Hasen hier 
wahrscheinlich soetwas zwischen Bügeln und Kaffee Kochen erledigen 
können!

PS: Khz routinen unvllständig ... noch




void ShowFrequencyOnDisplay(){

    // Wir muessen nicht immer neu-schreiben wenn keine Änderung erfolgt 
ist
    if(currentFrequencyDisplayRefresh==0) return;

    char* fr = calloc(35,sizeof(char));
    char* original = calloc(35,sizeof(char));

    ltoa(currentFrequency,original,10);

    if(currentFrequency>=100000000){
      // Wir arbeiten im 3 Stelligen Mhz Bereich
      strncpy(fr,original,3); // Einerstelle
      strncpy(fr+3,",",1); // Komma
      strncpy(fr+4,original+3,5);
      strncpy(fr+9," Mhz",5); // SUFFIX
    }
    else if(currentFrequency>=10000000){
      // Wir arbeiten im 2 Stelligen Mhz Bereich
      strncpy(fr,original,2); // Einerstelle
      strncpy(fr+2,",",1); // Komma
      strncpy(fr+3,original+2,5);
      strncpy(fr+8," Mhz",5); // SUFFIX

    }
    else if(currentFrequency>=1000000){
      // Wir arbeiten im 1 Stelligen Mhz Bereich
      strncpy(fr,original,1); // Einerstelle
      strncpy(fr+1,",",1); // Komma
      strncpy(fr+2,original+1,5);
      strncpy(fr+7," Mhz",5); // SUFFIX

    }
    else if(currentFrequency>=1000){
      // Wir arbeiten im Khz Bereich
      // TODO: ANNALOG WIE OBEN
    }
    else
    {
      // Wir haben nur Hertz, passiert aber ohnehin niemals :)
        LCDText("ERROR",2,2);
    }


    LCDText(fr,0,0);

    // Wir muessen nicht immer neu-schreiben wenn keine Änderung erfolgt 
ist
    currentFrequencyDisplayRefresh=0;


}
Gast
Damit es Anfänger Nahvollziehen können nochmal die Erklärung:

char* fr = calloc(35,sizeof(char));
char* original = calloc(35,sizeof(char));

Mit diesen zwei zeilen erstelle ich zwei 35 zeichen lange "Strings" die 
mit 0 gefüllt sind ... dies ist später nötig damit das LCD weiss wo 
schluss ist, denn 0 ist der terminate buchstabe.


Jetzt haben wir ein
long currentFrequency = 22344000;
welches wir mittels
ltoa(currentFrequency,original,10);
in unser original einlesen, dabei werden bis zu 10 stellen mit Nullen 
(nicht Terminal \0) gefüllt...


Nun ja und der Rest ist für jeden Mhz bereich gleich, nehmen wir z.B. 
die 3stelligen Mhz frequenzen:

  if(currentFrequency>=100000000){
      // Wir arbeiten im 3 Stelligen Mhz Bereich
      strncpy(fr,original,3); // Einerstelle
      strncpy(fr+3,",",1); // Komma
      strncpy(fr+4,original+3,5);
      strncpy(fr+9," Mhz",5); // SUFFIX
    }



Die Zeile
strncpy(fr,original,3);  (Äquivalent zu strncpy(fr+0,original,3); )
kopiert die ersten drei zeichen nach fr an die stelle 0, die erste 
stelle.

Dann kommt das komma was mittels
strncpy(fr+3,",",1); // Komma
Nach der 3ten Stelle angefügt wird (Merke: fr+3 ist der zeiger auf 
stelle 4, da wir von 0 an zählen)


Dann werden mit
  strncpy(fr+4,original+3,5);
nach dem Komma was an stelle fr+4 also quasi an der 5ten stelle 5 
Nachkommastellen angefügt ... Zum Glück haben wir oben gesagt dass wir 
den rest mit Nullen auffüllen wollen, sonst hätten wir ein Problem!


nun haben wir genau 3+1(komma)+5 Stellen Belegt, also 9 stellen.

Und mit
strncpy(fr+9," Mhz",5); // SUFFIX
kommt schlussendlich der Mhz Schriftzug nach der Stelle neun in unseren 
fr-String!


Mehr brauchen wir nicht zu tun, da Stelle 11 dann eh der terminale 
Nullcharakter ist und das Display weiss, hier ist sense!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.