www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Gleitkommazahlen


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich will mit dem internen AD-Wandler eines Atmega eine Spannungswert 
auslesen, in eine Gleitkommazahl umrechnen und auf einem LCD-Display 
anzeigen lassen.

Zum Beispiel: 1 Bit im ergebnissregister des ADW entspricht 54,244mV.
Ich will jetzt in V umrechnen auf eine Stelle hinterm Komma und auf 
einen LCD Display anzeigen lassen.

Könnte mir jemand helfen?

mfg peter

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ungeschickt.
Gleitkomma ist bäh.
Rechne es als Ganzzahl in mV aus, bei der Ausgabe verschiebst du dann 
das Komma um 3 Stellen und lässt die letzten 2 Stellen weg.
:-)

Autor: Andreas K. (derandi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Haste denn wenigstens schon mit was angefangen?

Autor: Peter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@Floh
die idee ist eigentlich gar nicht schlecht.

Hier ist mal mein gesammter Programmcode, aber intressant ist nur der 
Teil mit der Umrechnung. Ich habe ihn mit Anzeige Gleitkommazahl 
makiert.

mfg peter

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> Hier ist mal mein gesammter Programmcode

Du kommst aus der Assemblerecke. ;-)
Was du da im Programm versuchst, ist rjmp mit goto nachzubauen.
Ist eigentlich nicht zu empfehlen, da C selbst "bessere/gebräuchlichere" 
Strukturen mitbringt, als unbedingte Sprünge irgendwohin.
Stichwort Funktionen.

Oder z.B. so was:
>  Spannungswert = ADCH, ADCL;

da solltest du dich mal über den Kommaoperator schlau machen :-)

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Multiplikation:
Beitrag "Re: Float-Berechnung auf 8051 mit SDCC"


Ganz anderer Ansatz:
Nimm die Routinen zur Ausgabe von Zahlen von Peter Danegger, nur dass Du 
nicht dezimale Werte subtrahierst / addierst, sondern die Aquivalente zu 
1V, 0,1V etc.
Somit geht die Umwandlung ganz ohne Division und Multiplikation.
#include<stdio.h>
#include<conio.h>

char c;
unsigned int i=0x0123<<6;//linksbündig  entspricht 1,4208V ergibt 1,421
//wenn das ADLAR-Bit in ADMUX gesetzt ist, entfällt das Schieben um 6

void main(void){
  putch(' ');

  i=(   1<<6);  //ergibt 0,004
  i=(   1<<6)+2;//ergibt 0,005
//i=(1023<<6)+2;//ergibt 4,995

  c='0';
  while(i>=65536/   5){c++;i-=65536/   5;} //13107
  putch(c);putch(',');

  c='0';
  while(i>=65536/  50){c++;i-=65536/  50;} //1310
  putch(c);

  c='0';
  while(i>=65536/ 500){c++;i-=65536/ 500;} //131
  putch(c);

  c='0';
  while(i>=65536/5000){c++;i-=65536/5000;} //13
  putch(c);

  putch(' ');

  i=(1023<<6)+2;//ergibt 5,000

  c='0';
  while(i>=65472/   5){c++;i-=65472/   5;} //13094
  putch(c);putch(',');

  c='0';
  while(i>=65472/  50){c++;i-=65472/  50;} //1309
  putch(c);

  c='0';
  while(i>=65472/ 500){c++;i-=65472/ 500;} //130
  putch(c);

  c='0';
  while(i>=65472/5000){c++;i-=65472/5000;} //13
  putch(c);
  }


Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der vorige Ansatz war nur als Ideenspender gedacht, er funktioniert bei 
manchen Werten nicht korrekt (z.B. wird statt 0,210  0,20: ausgegeben).
Deshalb hier eine neue Version:

von den 1024 Werten weichen 26 um 0,001 vom korrekt gerundeten Wert ab, 
damit kann man leben.
  register unsigned int i;
  register char c;
  i=(   x<<6)+6;//Schieben entfällt bei ADLAR=1, +6: runden
//i=(1023<<6)+6;//Test: ergibt 4,995
  c='0';
  while(i>=13107){c++;i-=13107;} //13107.2
  putch(c);putch(',');

  c='0';i+=i*4;i-=2; //das selbe wie i=i*5-2; (-2: Korrektur, da vorher Nachkommastellen abgeschnitten wurden)
  while(i>= 6553){c++;i-= 6553;} //6553.6
  putch(c);

  c='0';i+=i*4;i*=2;i-=2; //das selbe wie i=10*i-2; aber kürzerer Code
  while(i>= 6553){c++;i-= 6553;}
  putch(c);

  c='0';i+=i*4;i*=2;i-=2;
  while(i>= 6553){c++;i-= 6553;}
  putch(c);
Das alternativ Subtrahieren / Addieren habe ich absichtlich nicht 
gemacht, da das Vorzeichen-Bit ein Bit Genauigkeit kostet.

Autor: df1as (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darf man kein printf() nehmen? Ansonsten:

unsigned long dV;

dV = ((unsigned long) ADC-Wert * 568789L) >> 20;
printf ("Spannung = %lu,%lu V", dV / 10, dV % 10);

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.