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


von Lukas B. (lukas-1992) Benutzerseite


Lesenswert?

Hallo,
ich Versuche schon eine ganze weile einen Floatwert über die UART - 
Schnittstelle (8 Databits ).
Der Floatwert ist so Aufgebaut: xxx.x
1
Ansatz 1:
2
Mit Printf, leider funktionierts nicht:
3
float float_wert;
4
char char_wert[10];
5
sprintf(char_wert,"%.1f",float_wert); 
6
7
Ansatz 2:
8
Zugriff auf den Floatwert mit Pointer,
9
Geht auch nicht, da nicht als Asci Übertragen wird.
10
11
unsigned char *p;
12
13
        p = (unsigned char) float_wert;
14
15
        char_wert[0]= *p++;
16
        char_wert[1]= *p++;
17
        char_wert[2]= *p++;
18
        char_wert[3]= *p;  
19
20
Ansatz 3:
21
Selbiges ASCI Problem wie Oben
22
    tmp3 = (int) float_wert;
23
    tmp5 = float_wert/100;
24
    tmp4 = (int) tmp5;

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

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


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?

von Purzel H. (hacky)


Lesenswert?

Float sollte man als 32bit, dh 4x 8bit uebertragen.

von Lukas B. (lukas-1992) Benutzerseite


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

von g457 (Gast)


Lesenswert?

> Mit Printf, leider funktionierts nicht:

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

HTH

von Lukas B. (lukas-1992) Benutzerseite


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

von g457 (Gast)


Lesenswert?

Sieht verdächtig nach falschem Takt oder falscher Baudrate aus..

http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

HTH

von Peter P. (ichbineinepfanne) Benutzerseite


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.

von holger (Gast)


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.

von Karl H. (kbuchegg)


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#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio

> 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

von Sam .. (sam1994)


Lesenswert?

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

von Lukas B. (lukas-1992) Benutzerseite


Lesenswert?

Das ist meine Main, in  welcher die Daten gesendet werden sollten:
1
#include <stdio.h>
2
3
int Init_Rs232()
4
  {
5
6
  UBRRL  =  77;    //Baud - Rate, 9600bps, UBRR = 
7
  UCSRA  =  0x40;
8
  UCSRB  =  0b10011000;  //TXD/RXD, kein TX-Interrup
9
  UCSRC  =  0b10000110;  //Aynchron, no parity, 1 stop, 8 Datenbits
10
11
  }
12
13
int Send_Rs232(char send)
14
  {
15
    delay_ms(50);
16
    UDR = send;
17
    return;
18
  }
19
20
int main (void)
21
{
22
  int count = 0;
23
  float temp_duzel;
24
  unsigned char temperatur_duzel[20];
25
26
  reader_init(tempsens_1);
27
  Init_Rs232();
28
29
  for(;;)
30
  {
31
    temp_duzel = reader_read_temp(tempsense_1);
32
    DDRC = 0xFF;    //LEDs als Ausgang
33
34
    sprintf(temperatur_duzel,"%.1f",temp_duzel);    
35
36
    while(count <=10)  // Gibt die Temperatur an der seriellen Schnittstelle aus.
37
    {
38
      Send_Rs232(temperatur_duzel[count]); // Sendet jeden char an die Serielle Schnittstelle
39
      count++;
40
    }
41
    count = 0; // Setzt den Zähler für die Ausgabe des char Arrays zurück
42
    PORTC = temp_duzel; // Zeigt das MSB auf den LED's an
43
44
45
  }
46
  
47
}

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

von Karl H. (kbuchegg)


Lesenswert?

Lukas B. schrieb:

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


Zu sprintf hab ich schon was geschrieben

http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio

>
>     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_funktioniert_String-Verarbeitung_in_C.3F


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-Tutorial/Der_UART
AVR-GCC-Tutorial

Dann schreibst du nicht mehr sowas
1
int Init_Rs232()
2
  {
3
4
  UBRRL  =  77;    //Baud - Rate, 9600bps, UBRR = 
5
  UCSRA  =  0x40;
6
  UCSRB  =  0b10011000;  //TXD/RXD, kein TX-Interrup
7
  UCSRC  =  0b10000110;  //Aynchron, no parity, 1 stop, 8 Datenbits
8
9
  }
sondern du schreibst es vernünftig, so dass man das auch lesen und vor 
allen Dingen auch warten kann.

von Lukas B. (lukas-1992) Benutzerseite


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.
1
int Init_Rs232()
2
  {
3
    UCSRA = 0x00;     // mit U2X könnte die Baudrate verdoppelt werden (nicht benötigt)
4
      UCSRB |= (1<<TXEN);  // Serielle Schnittstelle einschalten
5
      UCSRC = (1<<URSEL)|(1 << UCSZ1)|(1 << UCSZ0); // 8 Databits, 1 Stopbit
6
    UBRRH = (reg_ubrr>>8);
7
    UBRRL = reg_ubrr;
8
  }
9
10
int Send_Rs232(char send)
11
  {    
12
  // while (!(UCSRA & (1<<UDRE)))  
13
    while(!(UCSRA & TXC))
14
    { }//warten bis Senden möglich
15
    
16
    delay_ms(10);
17
    UDR = send;
18
    return;
19
  }

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

von Karl H. (kbuchegg)


Lesenswert?

Die 10ms delay wirfst du noch raus.

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.