Float über UART übertragen - STM8

OP #4558159
Lesenswert?

Hallo Forum,

ich versuche aktuell einen Float Wert eines Sensors über UART zu 
übertragen. µC ist hierbei ein STM8S103F3P6, UART/USB-Converter ein 
CH340-Modul.

Ich benutze ST Visual Develop als IDE und den Cosmic Compiler. Leider 
bietet mit diese Kombination keine Standard-C Funktionen, die es mir 
erlauben würden, den float in einen char umzuwandeln (zumindest hab ich 
diese noch nicht gefunden).

Daher stellt sich mir die Frage, wie ich die Werte nun als Float 
ausgeben kann?

Meine UARTSend-Funktion:
1
void UARTSend(char *message){
2
  char *ch = message;
3
  while(*ch){
4
    while(!(UART1->SR & (1<<6))); //Wait until transmission is complete
5
    UART1->DR = *ch;
6
    ch++;
7
  }
8
}

Ich hab in anderen Beitragen zu ähnlichen Themen gelesen, dass man den 
float in einzelne 8-bit Blöcke zerlegen kann und diese dann überträgt. 
Allerdings frage ich mich, wie ich die dann am anderen Ende wieder 
zusammenstückel? Funktioniert es, dass man den Float direkt als Char 
bzw. ASCII-Zeichenkette überträgt?

Falls die Lösung schon irgendwo steht, sry.
#4558163
Lesenswert?

> Daher stellt sich mir die Frage, wie ich die Werte nun als Float
> ausgeben kann?
>
> Ich hab in anderen Beitragen zu ähnlichen Themen gelesen, dass man den
> float in einzelne 8-bit Blöcke zerlegen kann und diese dann überträgt.
> Allerdings frage ich mich, wie ich die dann am anderen Ende wieder
> zusammenstückel? Funktioniert es, dass man den Float direkt als Char
> bzw. ASCII-Zeichenkette überträgt?
>
> Falls die Lösung schon irgendwo steht, sry.

Kein sprintf? Kannst den float auch binär übertragen. Das Format ist 
standardisiert.
Gast #4558168
Lesenswert?

Max M. schrieb:
> Allerdings frage ich mich, wie ich die dann am anderen Ende wieder
> zusammenstückel?

Bevor du sie zusammenstückeln kannst, muss du erstmal wissen, wo die 
Übertragung eines neuen Werten beginnt. Du brauchst ein Datenformat, 
dass eine Synchronisationsinformation enthält.

> Funktioniert es, dass man den Float direkt als Char bzw. ASCII-
> Zeichenkette überträgt?

Der Übertragungsstrecke ist es egal, was in deinen Augen die 
übertragenen Zeichen bedeuten. Da muss sich die Empfangsroutine drum 
kümmern.
OP #4558202
Lesenswert?

Funktioniert es vllt. wenn ich den Float einfach * 1000 nehme (passt ja 
noch in ein uint16_t) und dann diese uint16_t in chars umwandel? Wie 
würde das funktionieren?

The D. schrieb:
> Kein sprintf?

Nope :(

The D. schrieb:
> Kannst den float auch binär übertragen. Das Format ist
> standardisiert.

Ich hätte das ganze halt schon gerne als Text auf der Konsole und nicht 
als '1' und '0'.
#4558213
Lesenswert?

Max M. schrieb:
> Funktioniert es vllt. wenn ich den Float einfach * 1000 nehme (passt ja
> noch in ein uint16_t) und dann diese uint16_t in chars umwandel? Wie
> würde das funktionieren?
>
> The D. schrieb:
>> Kein sprintf?
>
> Nope :(
>
> The D. schrieb:
>> Kannst den float auch binär übertragen. Das Format ist
>> standardisiert.
>
> Ich hätte das ganze halt schon gerne als Text auf der Konsole und nicht
> als '1' und '0'.

Dann kommst du nicht um eine manuelle Konvertierung herum. Also den 
Integer Anteil umwandeln und dann in einer Schleife mit 10 
multiplizieren und wieder den integer Anteil umwandeln. Die Anzahl der 
Schleifendurchläufe bestimmt die Genauigkeit.
OP #4558246
Lesenswert?

The D. schrieb:
> Dann kommst du nicht um eine manuelle Konvertierung herum. Also den
> Integer Anteil umwandeln und dann in einer Schleife mit 10
> multiplizieren und wieder den integer Anteil umwandeln. Die Anzahl der
> Schleifendurchläufe bestimmt die Genauigkeit.

Könntest du da netterweise ein kurzes Beispiel zeigen, was du genau 
meinst?

Mein Code aktuell:
1
uint16_t x,y,z;
2
uint8_t x1,x2;
3
readXYZ(&x,&y,&z);
4
x1 = (x & (0xFF00)) >> 8;
5
x2 = x & (0x00FF);

x1 und x2 stellen die 8-Bit Anteile der 16-Bit Zahl x dar. Warum 
muss ich die nun mit 10 multiplizieren?
Gast #4558372
Lesenswert?

Servus,
über uart kann man nur 8 bits übertragen, d.h. für einen float braucht 
man 4 bytes. Hier ist es auch wichtig zu wissen, welche Endianess die 
beiden µC besitzen, sodass es villt notwendig sei die bytes zu 
"swappen".

Nun gut:
1
#define SIZE_FLOAT          sizeof(float) //kann man auch gleich 4 schreiben
2
        
3
uint8_t array_Rx[100];  // RX array
4
float var_fl;
5

6
//hier die richitge bibiothek einfügen für memcpy
7
memcpy(&(array_Rx[x]) , &var_fl,  SIZE_FLOAT); //fuer x die richtige stelle reinschreiben!
8

9
//Als Alternative geht es auch mit den Verschiebeoperator >><< oder event auch so:
10
uint32_t schiebab;
11
schiebab = (uint32_t)array[x]; //wenn die Endiannes passt sonst muss man schieben
12

13
var_fl = (float)schiebab;
14

15
typedef union{
16
float var_fl;
17
uint8_t[4] array;
18
}BYTE_TO_FLOAT_u;
19
 
20
BYTE_TO_FLOAT_u kann_ab_bis;
21

22
kann_ab_bis.uint8_t[0] = array[0];
23
kann_ab_bis.uint8_t[1] = array[1]
24
...
25
//bitte eine Schleife drum rum wickeln!
26

27
var_fl = kann_ab_bis.var_fl;


mfg
#4558375
Lesenswert?

aSma>> schrieb:
> Servus,
> über uart kann man nur 8 bits übertragen, d.h. für einen float braucht
> man 4 bytes. Hier ist es auch wichtig zu wissen, welche Endianess die
> beiden µC besitzen, sodass es villt notwendig sei die bytes zu
> "swappen".
>

Er will es ja als lesbaren Text übertragen und nicht die 
Binärdarstellung. Im übrigen ist deine Ausführung Unsinn weil die IEEE 
Darstellung auf allen Plattformen identisch ist. Swappen muss man die 
bytes nur für Integers wenn man sie zwischen big endian und little 
endian Plattformen austauschen will.
OP #4558508
Lesenswert?

Stimmt, du hast recht ^^.

Aber es gibt kein itoa und nur sprintf zum konvertieren. Leider 
funktioniert dieser Code hier nicht:
1
    float x,y,z;
2
    char buffer_x[255];
3
    char buffer_y[255];
4
    char buffer_z[255];
5
    readXYZ(&x,&y,&z);
6
    sprintf(buffer_x, "%-.5f",x);
7
    sprintf(buffer_y, "%-.5f",y);
8
    sprintf(buffer_z, "%-.5f",z);

Nur wenn ich *%d* als Format benutze, bekomme ich was in die Konsole 
geschrieben, so bleibt die einfach leer.

Edit: Diese FAQs von denen sind ja schön und gut aber nirgends steht wo 
man die Dateien tatsächlich findet? Mir ist inzwischen klar, warum sie 
ihren Compiler ohne Begrenzung weggeben, bei der ausführlichen Doku 
benutzt den sicher jeder gerne.
Gast #4558553
Lesenswert?

Max M. schrieb:
> Edit: Diese FAQs von denen sind ja schön und gut aber nirgends steht wo
> man die Dateien tatsächlich findet? Mir ist inzwischen klar, warum sie
> ihren Compiler ohne Begrenzung weggeben, bei der ausführlichen Doku
> benutzt den sicher jeder gerne.

Unter dem Punkt: Eigene Umwandlungsfunktionen
ist die Fkt. : void ItoA( int z, char* Buffer ) von den Macher K&R, in 
vollster Länge aufgeschrieben. Was will man da mehr? Der Rest ist in 10 
min zusammen gefriemelt.

Oder du bedienst dich hier im Forum:
Beitrag "Re: C-Umwandlungsfunktionen für double/int/long nach String"

Eine echt klasse lib. Einfach nur ein paar Datentypen ändern und schon 
läuft der Rubbel.
#4558628
Lesenswert?

Ich habe letzte Woche an einer eigenen sehr minimalistischen printf - 
Funktion gebastelt (allerdings für einen AVR - grundsätzlich für einen 
ATtiny) der eben sehr Speicherplatzsparend sein sollte...

Eine echte Float-Ausgabe gibts nicht, aber er gibt eine Zahl mit 2 
Nachkommastellen aus (welche mir sehr oft für ausgelesene Sensoren 
reicht) mit einem Beispiel wie ein 10-Bit ADC als Spannungswert 
angezeigt werden kann.

Vllt. hilft dir das hier:

Beitrag "Re: #define Ich bekomme ein Makro nicht hin."

Hier mußt du die Funktionen der seriellen Schnittstelle natürlich selbst 
definieren und das AVR - eigene Auslesen eines Strings aus dem Flash 
(pgm_read_byte) ersetzen...

Smile, werde ich auch ganz sicher noch auf einem STM8 ausprobieren... 
sobald meiner aus China hier eingetroffen ist...

Gute Nacht
#4558723
Lesenswert?

Sinnvollerweise legt man ein Byte Array und den float aufeinander, dann 
kann man float nach byte wandeln. Wenn man nun ASCII uebertragen will, 
macht man aus jedem Byte einen Hex.
Auf der anderen Seite Hext to Byte und in den Byte array, von dort den 
Float auslesen. egal ob 32bit oder 64bit.
(Firma: Torrox.de) #4558948
Lesenswert?

Max M. schrieb:
> Daher stellt sich mir die Frage, wie ich die Werte nun als Float
> ausgeben kann?

Ich stelle mir gerade die Frage, wie Du auf einem STM8 überhaupt zu 
einem float gekommen bist? Das erste und letzte mal, als ich mit einem 
STM8 gearbeitet habe, wäre ich im Leben nicht auf die Idee gekommen, den 
kleinen 8-Bitter mit Mathe zu quälen ;-)

Wäre eine Festkomma-Zahl nicht viel passender? Einen float braucht man 
doch wirklich nur dann, wenn der Exponent auch mal mehr als eine paar 
neben einander liegende Werte annehmen kann.
OP #4558964
Lesenswert?

Torsten R. schrieb:
> Wäre eine Festkomma-Zahl nicht viel passender? Einen float braucht man
> doch wirklich nur dann, wenn der Exponent auch mal mehr als eine paar
> neben einander liegende Werte annehmen kann.

Es handelt sich um einen Beschleunigungssensor der Werte in mG liefert. 
Ich hätte halt schon ganz gerne echte "G" (also z.B. 1,243G) und nicht 
1243 mG. Oder doch lieber Ganzzahlen?

aSma>> schrieb:
> Oder du bedienst dich hier im Forum:

Vielen Dank, genau das, was ich suche!
#4559142
Lesenswert?

Torsten R. schrieb:
> Ich stelle mir gerade die Frage, wie Du auf einem STM8 überhaupt zu
> einem float gekommen bist? Das erste und letzte mal, als ich mit einem
> STM8 gearbeitet habe, wäre ich im Leben nicht auf die Idee gekommen, den
> kleinen 8-Bitter mit Mathe zu quälen ;-)

OT: ich habe in den 90-ern noch mein Z80-Homecomputer Mandelbrötchen 
backen lassen in BASIC: 8-bit, Mathe und Interpreter. Langsamer geht 
nicht :-D Und dann nach eine Nacht rechnen feststellen, dass das 
Programm mit einem "Syntax Error" oder "Out of Memory" verabschiedet 
hat...
Persönliche Seite #4559143
Lesenswert?

Torsten R. schrieb:
> Ich stelle mir gerade die Frage, wie Du auf einem STM8 überhaupt zu
> einem float gekommen bist? Das erste und letzte mal, als ich mit einem
> STM8 gearbeitet habe, wäre ich im Leben nicht auf die Idee gekommen, den
> kleinen 8-Bitter mit Mathe zu quälen ;-)

Aber manchmal braucht man halt ein bischen Mathe. Ich hatte beim STM8 
letzten auch float verwendet um schnell etwas zu probieren. Was mich 
erstaunte war, dass zumindest mit dem Cosmic Compiler, Rechnungen in 
float um einiges schneller waren als einen uin32_t durch 10 zu teilen :)
#4559155
Lesenswert?

Max M. schrieb:
> Torsten R. schrieb:
>> Wäre eine Festkomma-Zahl nicht viel passender? Einen float braucht man
>> doch wirklich nur dann, wenn der Exponent auch mal mehr als eine paar
>> neben einander liegende Werte annehmen kann.
>
> Es handelt sich um einen Beschleunigungssensor der Werte in mG liefert.

Dann übertrage doch die Werte in mG und mach die Umsetzung am PC!
Gast #4559209
Lesenswert?

wie wäre es damit:
1
//____________________________________________________
2
//wandelt Float in IEEE754-32bit
3
uint32 cmd_FloatToIEEE754(float In)
4
{  float xFloat;
5
  uint32 xUint32;
6
  
7
  xFloat=In;
8
  xUint32 = *(uint32*)(&xFloat);
9
  return xUint32;
10
}
11
//____________________________________________________
12
//wandelt IEEE754-32bit in Float
13
float cmd_IEEE754ToFloat(uint32 In)
14
{  float xFloat;
15
  uint32 xUint32;
16
  
17
  xUint32=In;
18
  xFloat = *(float*)(&xUint32);
19
  return xFloat;
20
}
#4559239
Lesenswert?

Max M. schrieb:
> Torsten R. schrieb:
>> Dann musst Du den Integer aber nicht erst in einen Text umwandeln...
>
> Stimmt, man kann in das Datenregister auch eine uint8_t Ganzzahl
> reinschieben, oder? Dann müsste ich meine 16-bit aber in 2 Zahlen
> unterteilen. Die Frage ist, was dann schneller geht.

Ist das eine ernst gemeinte Frage ?

Auf der einen Seite Umwandlung in Text, dann ca. 6 Bytes 
Datenübertragung. Auf der anderen Seite einfach nur 2 bytes übertragen. 
Was da wohl schneller ist ...
(Firma: Torrox.de) #4559265
Lesenswert?

Max M. schrieb:
> Torsten R. schrieb:
>> Dann musst Du den Integer aber nicht erst in einen Text umwandeln...
>
> Stimmt, man kann in das Datenregister auch eine uint8_t Ganzzahl
> reinschieben, oder? Dann müsste ich meine 16-bit aber in 2 Zahlen
> unterteilen. Die Frage ist, was dann schneller geht.

Ja, wahrscheinlich hat das Datenregister sogar den typen uint8_t. Und 2 
Bytes zu übertragen ist viiiieel schneller.
OP #4559387
Lesenswert?

The D. schrieb:
> Doch, nimmt es.

In dieser Funktion?
1
char * ltoa(char * buf, int16_t val, char pad){
2
  char i;
3
  char tmp_buf[10];
4

5
  for(i=0; val>0; val/=10)
6
    tmp_buf[i++] = (val % 10) + '0';
7
  if(i==0)
8
    tmp_buf[i++] = '0';
9

10
  while(i<pad)
11
    tmp_buf[i++] = '0';
12

13
  while(i>0)
14
    *buf++ = tmp_buf[--i];
15

16
  *buf = 0;
17

18
  return buf;
19
}
Gast #4559731
Lesenswert?

The D. schrieb:
> Die Funktion dürfte recht interessante Ergebnisse für negative Integer
> liefern. So wie sie ist sollte der zweite Parameter besser den Typ
> uint16_t haben.

Richtig! Hier das original:
1
char * ltoa(char * buf, unsigned long val, char pad)

Sonst nehme die !SIMPLE ltoa fkt. Das ist dann mit Vorzeichen Erkennung.
#4560706
Lesenswert?

Hallo Max

Wenn du die Daten binär überträgst, benötigst du auf der PC-Seite ein 
Auswerteprogramm. Das würde ich nur empfehlen, wenn du mit der 
Geschwindigkeit nicht hinkommst.

Hast du meinen Vorschlag "printfk.txt" überhaupt angeschaut?
Beitrag "Re: Float über UART übertragen - STM8"

Die Daten können damit in Text umgewandelt und Buchstabenweise gesendet 
werden. HTerm empfängt, zeigt an, und kann exportieren.
http://www.der-hammer.info/terminal/

Selbst wenn du nur mit 9600 Baud sendest, dauert die Übertragung von 
einem Buchstaben ca. 1ms. Eine Zahl im Format -3,456 dauert dann 6ms, 
bei drei Achsen (x, y, z) 18ms. Wenn das zu langsam ist, kannst du auf 
115200 Baud hoch, dann geht alles 10 mal so schnell.

Du übergibst deine milli-G, das Komma an der 3. Stelle und das 
Vorzeichen wird auch ausgewertet.
1
char ausgabe[13];
2
char len, i;
3
int16_t x, y, z;
4

5
readXYZ(&x,&y,&z); // Vorzeichenbehaftete Werte in mG
6
len = printfk(x, ausgabe, 10, 3, ','); // Print Festkomma
7

8
for (i=0; i<len; i++) {
9
  TXREG = ausgabe[i];   // schreibt ein Byte auf das TX-Register
10
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren