mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Float - Wert über UART setzten


Autor: Lukas B. (lukas-1992) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich Versuche schon eine ganze weile einen Floatwert über die UART - 
Schnittstelle (8 Databits ).
Der Floatwert ist so Aufgebaut: xxx.x
Ansatz 1:
Mit Printf, leider funktionierts nicht:
float float_wert;
char char_wert[10];
sprintf(char_wert,"%.1f",float_wert); 

Ansatz 2:
Zugriff auf den Floatwert mit Pointer,
Geht auch nicht, da nicht als Asci Übertragen wird.

unsigned char *p;

        p = (unsigned char) float_wert;

        char_wert[0]= *p++;
        char_wert[1]= *p++;
        char_wert[2]= *p++;
        char_wert[3]= *p;  

Ansatz 3:
Selbiges ASCI Problem wie Oben
    tmp3 = (int) float_wert;
    tmp5 = float_wert/100;
    tmp4 = (int) tmp5;

Wielange die Konvertierung dauert ist mir eigentlich egal (nicht länger 
al 5s) Kann mir jemand weiterhelfen?
Grüße
Lukas

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

Bewertung
0 lesenswert
nicht lesenswert
Lukas B. schrieb:
> ich Versuche schon eine ganze weile einen Floatwert über die UART -
> Schnittstelle (8 Databits ).
Was denn? ... zu senden   oder  ... zu empfangen?

> Mit Printf, leider funktionierts nicht:
Woran liegts?

Und was noch offen ist:
Welcher uC?
Welcher Compiler?
Welche Libraries?

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Float sollte man als 32bit, dh 4x 8bit uebertragen.

Autor: Lukas B. (lukas-1992) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pardon, habe noch ein par wichtige sachen Vergessen.
Ich möchte den Floatwert über die Serielle Schnittstelle senden, Wenn 
ich einfache Chars sende funktionierts, die initialisierung bzw. die 
Schnittstelle arbeitet richtig.
Ich arbeite mit einem ATMEGA16 mit 12MHz Quarz.
Programmiert habe ich den obigen Code in GCC mit dem aktuellen 
GCC-Compiler in WinAVR 4.18.
Ich verwende die Standartlibarys vom GCC.
Grüße Lukas

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mit Printf, leider funktionierts nicht:

Was heisst 'funktioniert nicht'? Kommt vielleicht nur ein Fragezeichen 
('?') an?

HTH

Autor: Lukas B. (lukas-1992) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein es kommt folgendes an:
>?àC<0>N"?àC<0>?àC<0>N"?àC<0>?à
dieses Zeugs ändert sich auch mit dem verändern der Float Variable

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieht verdächtig nach falschem Takt oder falscher Baudrate aus..

http://www.mikrocontroller.net/articles/AVR_Checkl...

HTH

Autor: Peter Pfanne (ichbineinepfanne) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag ... ich war wohl zu spät, aber vielleicht ist es ja trotzdem 
nützlich:




Die Umwandlung in Ascii ist eigentlich recht einfach dank dem Aufbau der 
Ascii-Tabelle. http://www.asciitable.com/
Du musst dir nur überlegen welche Arithmetische Operation du ausführen 
musst.

In deinem Fall:
Willst aus einer Zahl "1" eine Asciizeichen "1" erstellen musst du 
(dezimal) 48 Addieren.
1+48 = 49 (dezimal ascii "1")
Gleiches Prinzip gilt auch bei Wandlung in groß/kleinbuchstaben o.Ä.
Funktioniert natürlich nur sinnvoll bei Char bzw. wenn man sich sicher 
ist was mit dem "überschuss" wie z.B. bei einer Integer passiert.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Nein es kommt folgendes an:
>>?àC<0>N"?àC<0>?àC<0>N"?àC<0>?à

Wann kommt das an? sprintf() sollte eigentlich funktionieren.
Da es keinen kompletten Code gibt ist hier einfach Feierabend.
Zum raten ist mir die Zeit zu schade.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lukas B. schrieb:
> Hallo,
> ich Versuche schon eine ganze weile einen Floatwert über die UART -
> Schnittstelle (8 Databits ).
> Der Floatwert ist so Aufgebaut: xxx.x
>
> [c]
> Ansatz 1:
> Mit Printf, leider funktionierts nicht:
> float float_wert;
> char char_wert[10];
> sprintf(char_wert,"%.1f",float_wert);


Doch das funktioniert schon. Aber du musst die floating Point Version 
von sprintf aktivieren.

http://www.mikrocontroller.net/articles/FAQ#Aktivi...

> Ansatz 2:
> Zugriff auf den Floatwert mit Pointer,
> Geht auch nicht, da nicht als Asci Übertragen wird.

Eben.
Diese Version legst du am besten gleich wieder ad acta

Autor: Sam .. (sam1994)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du nur ASCII übertragen willst sende einfach 8 4bit Blöcke und 
übertrage dann z.b. so: 'a' + wert

Autor: Lukas B. (lukas-1992) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist meine Main, in  welcher die Daten gesendet werden sollten:
#include <stdio.h>

int Init_Rs232()
  {

  UBRRL  =  77;    //Baud - Rate, 9600bps, UBRR = 
  UCSRA  =  0x40;
  UCSRB  =  0b10011000;  //TXD/RXD, kein TX-Interrup
  UCSRC  =  0b10000110;  //Aynchron, no parity, 1 stop, 8 Datenbits

  }

int Send_Rs232(char send)
  {
    delay_ms(50);
    UDR = send;
    return;
  }

int main (void)
{
  int count = 0;
  float temp_duzel;
  unsigned char temperatur_duzel[20];

  reader_init(tempsens_1);
  Init_Rs232();

  for(;;)
  {
    temp_duzel = reader_read_temp(tempsense_1);
    DDRC = 0xFF;    //LEDs als Ausgang

    sprintf(temperatur_duzel,"%.1f",temp_duzel);    

    while(count <=10)  // Gibt die Temperatur an der seriellen Schnittstelle aus.
    {
      Send_Rs232(temperatur_duzel[count]); // Sendet jeden char an die Serielle Schnittstelle
      count++;
    }
    count = 0; // Setzt den Zähler für die Ausgabe des char Arrays zurück
    PORTC = temp_duzel; // Zeigt das MSB auf den LED's an


  }
  
}

Die UART müsste richtig funktionieren, wenn ich zum Beispiel schreibe:
Send_Rs232('A');
kommt auf dem Terminal laufend A.
Daraus Schlussfolgere ich das die Serielle Schnittstelle funktioniert.

Grüße Lukas

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lukas B. schrieb:

>
>     sprintf(temperatur_duzel,"%.1f",temp_duzel);


Zu sprintf hab ich schon was geschrieben

http://www.mikrocontroller.net/articles/FAQ#Aktivi...

>
>     while(count <=10)  // Gibt die Temperatur an der seriellen
> Schnittstelle aus.

Na da wundert mich dein Output jetzt nicht mehr.
Du kannst doch nicht einfach annehmen, dass jeder String 11 Zeichen hat!
Schreib dir als erstes mal eine vernünftige String Ausgabefunktion!

Jeder String hört mit einem '\0' Zeichen auf! Das kann man ausnutzen und 
solange Zeichen ausgeben, bis man auf dieses '\0' Zeichen stösst.

http://www.mikrocontroller.net/articles/FAQ#Wie_fu...


Aber bitte nicht in main.
Dafür schreibt man sich eine eigene Funktion! Denn Stringausgabe braucht 
man alle Nase lang.

Auch kann ein Blick ins Tutorial zum Thema UART nicht schaden
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
AVR-GCC-Tutorial

Dann schreibst du nicht mehr sowas
int Init_Rs232()
  {

  UBRRL  =  77;    //Baud - Rate, 9600bps, UBRR = 
  UCSRA  =  0x40;
  UCSRB  =  0b10011000;  //TXD/RXD, kein TX-Interrup
  UCSRC  =  0b10000110;  //Aynchron, no parity, 1 stop, 8 Datenbits

  }
sondern du schreibst es vernünftig, so dass man das auch lesen und vor 
allen Dingen auch warten kann.

Autor: Lukas B. (lukas-1992) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank Karl Heiz!!!!


Ich habe übrigens das Programm ein wenig "leserlicher" geschrieben, 
allerdings suchte ich überall nur nicht beim Printf und der Floating 
Funktion, darauf wäre ich nie gekommen!

Ich Verwende in der fertigen Schaltung einen ATMEGA8, da ich aber 
probleme hatte mit dem floating Zeugs habe ich den ATMEGA16 verwendet.
int Init_Rs232()
  {
    UCSRA = 0x00;     // mit U2X könnte die Baudrate verdoppelt werden (nicht benötigt)
      UCSRB |= (1<<TXEN);  // Serielle Schnittstelle einschalten
      UCSRC = (1<<URSEL)|(1 << UCSZ1)|(1 << UCSZ0); // 8 Databits, 1 Stopbit
    UBRRH = (reg_ubrr>>8);
    UBRRL = reg_ubrr;
  }

int Send_Rs232(char send)
  {    
  // while (!(UCSRA & (1<<UDRE)))  
    while(!(UCSRA & TXC))
    { }//warten bis Senden möglich
    
    delay_ms(10);
    UDR = send;
    return;
  }


wenn das Programm fertig ist und funktioniert werde ich es hier 
Veröffentlichen, da vieleicht andere dieses Verwenden können.
(Es handelt sich dabei ums auslesen eines DS18S20 1Wire 
Temperatursensors)

Viele Grüße
Lukas

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die 10ms delay wirfst du noch raus.

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.