mikrocontroller.net

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


Autor: Cagara (Gast)
Datum:

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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

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

Autor: holger (Gast)
Datum:

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

Autor: A. K. (prx)
Datum:

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

Autor: aha (Gast)
Datum:

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

Autor: Marcus Woletz (Gast)
Datum:

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

Autor: Cagara (Gast)
Datum:

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


}

Autor: Cagara (Gast)
Datum:

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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>    char* fr = calloc(35,sizeof(char));

Wo sind die free() ?

Autor: Cagara (Gast)
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

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.