Forum: Mikrocontroller und Digitale Elektronik AVR: Effizienzter weg gesucht um Hertz in Mehahertz umzurechen


von Cagara (Gast)


Lesenswert?

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?

von Benedikt K. (benedikt)


Lesenswert?

Die einfachste Lösung: Vor die 6. Stelle (von rechts aus gesehen) 
einfach das Komma auf dem Display setzen.

von holger (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von aha (Gast)


Lesenswert?

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.

von Marcus Woletz (Gast)


Lesenswert?

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

von Cagara (Gast)


Lesenswert?

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;


}

von Cagara (Gast)


Lesenswert?

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!

von holger (Gast)


Lesenswert?

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

Wo sind die free() ?

von Cagara (Gast)


Lesenswert?

holger, die habe ich natürlich vergessen :)
schäm

Ewig-Steigende Memory Footprints wollen wir natürlich auch in dem AVR 
nicht haben!

Danke für den Hinweis!!!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> // Wir muessen ...
> // Wir arbeiten ...
> // Wir haben ...
Wieso eigentlich immer WIR?
ICH nicht mehr!
Gute Nacht ;-)

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
Noch kein Account? Hier anmelden.