Subroutine per la stampa di un floating point

  • firstcolle
  • Platino Utente
  • Platino Utente
Di più
8 Anni 4 Mesi fa #21 da firstcolle
Risposta da firstcolle al topic Subroutine per la stampa di un floating point
Molto interessante la tua soluzione!!!
posto anche la mia. praticamente do in input il float e quanti decimagli voglio scrivere sul display. La funzione converte in intero la parte intera e in stringa la parte decimale ed approssima l'ultimo decimale per eccesso.
poi scrive su LCD l'intero come signed int la virgola e la stringa dei decimali.

Purtroppo in questo modo ci sono dei casi ambigui con valori compresi tra -1 e 0 che mi ha costretto ad inserire una forzatura di stampa del - se il float iniziale è compreso tra -1 e 0. (questo succede perchè, prendendo per esempio -0.5, estraggo l'intero ed è 0 e quindi perdo il segno -)
Code:
void LCD_send_float (float _float, unsigned char _digits) { signed int _int = 0; float _part = 0; unsigned char _string[11]; unsigned char _i = 0; unsigned char _force_negative = 0; if (_digits > 10) // valore massimo di decimali = 10 _digits = 10; _int = (int) _float; // estraggo la parte intera _part = _float - (float)_int; // lascio solo la parte decimale if (_part<0){ // se decimali minore di 0 _part = _part * -1; // porto positiva if (_int == 0) // valore compreso tra -1 e 0 _force_negative = 1; // forzo valore negativo } for (_i = 0; _i < _digits +1; _i++ ){ // per ogni decimale richiesto +1 _part = _part *10; // moltiplico per 10 _string[_i] = (unsigned char)_part; // salvo nella stringa _part = _part - (float) _string[_i]; // dalla parte decimale sottraggo la nuova intera } // calcoli per l'approssimazione if (_digits == 0) { // 0 cifre decimali if (_string[0] > 4){ // se la prima decimale è maggiore di 4 aggiungo 1 agli interi if (_int >= 0) // se positivo _int++; else // altrimenti sottraggo 1 _int--; } } else { // se ho più cifre decimali if (_string[_digits] > 4){ // se l'ultima decimale (aggiunta solo per l'arrotondamento) è maggiore di 4 _string[_digits - 1]++; // aggiungo uno alla decimale precedente } for (_i = 0; _i < _digits -1; _i++ ){ // controlla dalla penultima decimale alla prima if (_string[_digits - 1 - _i] > 9){ // se maggiore di 9 _string[_digits - 1 - _i] = 0; // la porto a 0 _string[_digits - 2 - _i]++; // e aggiungo uno alla precedente } } if (_string[0] > 9){ // se la prima decimale è maggiore di 9 _string[0] = 0; // la azzero e incremento o decremento gli interi if (_int >= 0) _int++; else _int--; } } for (_i = 0; _i < _digits +1; _i++ ){ _string[_i] = _string[_i] + 0b00110000; // formo array di caratteri char con i numeri decimali } _string[_digits] = '\0'; // aggiungo carattere di fine stringa (array da 0 a _digit-1 contiene i numeri decimali richiesti) if (_force_negative) // valore compreso tra -1 e 0 LCD_send_char('-'); // forzo segno -, altrimenti verrebbe mostrato 0 senza segno LCD_send_sint(_int); // scrivo la parte intera if (_digits > 0) { // se sono richieste cifre decimali LCD_send_char(','); // scrivo ',' e decimali LCD_send_string(_string); } }

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • paoletto
  • Autore della discussione
  • Elit Utente
  • Elit Utente
Di più
8 Anni 4 Mesi fa #22 da paoletto
Risposta da paoletto al topic Subroutine per la stampa di un floating point
Alt, c'è un errore mostruoso nel codice :S , non funziona un bel niente :silly: .
E' sbagliata la mia soluzione dal momento che è inutile ripulire tutta la stringa finale con spazi bianchi: la stringa finale occorrente avrà il suo bel terminatore di fine stringa e la funzione di Mauro write_string_LCD() si fermerà non appena troverà la prima occorrenza del suddetto terminatore, ma la nuova stringa potrebbe essere più corta della precedente e quindi il suo terminatore sarà più giù e questo significa che i caratteri rimasti della stringa precedente non verranno mai ripuliti.
La soluzione è concatenare alla stringa occorrente(TempString)semplicemente una stringa di spazi bianchi di lunghezza pari a N-strlen(TempString) dove N è la profondità del display.

Posto il codice
Code:
//Numero caratteri del display(20 0 16) #define SizeCharDisplay 20 //Prototipo void PrintFloatOnString(const char *Token1, float measure, char SizeMeasure, const char *Token2); //corpo void PrintFloatOnString(const char *Token1, float measure, char SizeMeasure, const char *Token2) { size_t i; char String_Empty_Spaces[SizeCharDisplay+1] = ""; char measure_float[SizeCharDisplay+1]= ""; char StrToken1[SizeCharDisplay+1] = ""; char StrToken2[SizeCharDisplay+1] = ""; char TempString[SizeCharDisplay+1] = ""; char EndString[SizeCharDisplay+1] = ""; strcpy(StrToken1,Token1); strcpy(StrToken2,Token2); strcpy(TempString, StrToken1); FloatToString(measure_float, measure, SizeMeasure); strcat(TempString, measure_float); strcat(TempString, StrToken2); for(i = 0; i < SizeCharDisplay-strlen(TempString); i++) { String_Empty_Spaces[i] = ' '; //spazi bianchi } String_Empty_Spaces[++i] = '\0'; //terminatore di fine stringa strcat(TempString, String_Empty_Spaces); strcpy(EndString, TempString); write_string_LCD(EndString);//stringa finale } //uso main() { while(1) { PrintFloatOnString("Vrms: ", RMS_Value, 3, " V"); //3 è il numero di cifre decimali } }



La funzione concatena 3 token: la grandezza da misurare, il suo valore e la sua unità di misura.
Bisogna fare attenzione a non esagerare con la lunghezza dei token, devono essere i più identificativi possibile altrimenti non funziona, cioè bisogna farsi due conti e cercare di restare entro i 16 0 20 caratteri complessivi.
Per adesso funziona molto bene e non ho visto anomalie.
Il codice è sempre fatto per il C2000 ma è general purpose.

Per favore, chi abbia tempo usi la funzione e mi dia un feedback.

Grazie
Paolo.

Si prega Accesso o Crea un account a partecipare alla conversazione.

Moderatori: Mauro LaurentiStefA

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.

Forum - Ultimi messaggi