[Programmation] Alternative à la commande "sprintf"
Répondre à la discussion
Affichage des résultats 1 à 22 sur 22

Alternative à la commande "sprintf"



  1. #1
    tomjcb

    Alternative à la commande "sprintf"


    ------

    Bonjour à tous

    Je viens à vous, encore une fois, car j'ai un léger problème lié à la programmation, je précise, je programme en .c sous MPLABX avec le compilateur XC8.

    J'ai fais un programme qui est fonctionnel, qui gère un afficheur LCD et trois boutons.

    Le problème, c'est que, à l'aide des boutons, j'incrémente ou je décrémente une valeur, et cette fameuse valeur (qui est un int) doit être affichée sur l'écran LCD (qui est un écran OLED 4x20).

    Jusqu'ici, vous me direz surement, rien de bien sorcier. Et en effet, j'avais très vite trouvé une solution en utilisant la fonction sprintf, qui marche très bien pour convertir le int en chaîne de caractères. Mais le soucis c'est que je l'utilise plusieurs fois dans mon programme, et il se trouve qu'elle consomme énormément dans le programme.
    Pour 7 "sprintf", cela consomme déjà 37% de mémoire du PIC ce qui est énorme.

    Je voulais donc savoir si vous aviez une alternative à cette fonction, quelque chose de moins gourmand en ressources.

    (PS : J'ai bien évidemment fais quelques recherches, et j'ai trouvé une fonction appelée "itoa", mais je n'arrive pas du tout à la mettre en application ...)

    Bien à vous, Tom.

    -----
    Dernière modification par tomjcb ; 17/05/2018 à 15h37.
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

  2. #2
    SRO2

    Re : Alternative à la commande "sprintf"

    Salut !

    Lorsque tu dis 37% de la mémoire c'est bien de la mémoire RAM dont tu parles ? (pas de la ROM)

    Est ce possible de poster ton code pour voir si cette consommation de mémoire vient vraiment de la fonction "sprintf" ?

  3. #3
    tomjcb

    Re : Alternative à la commande "sprintf"

    Bonjour !

    Eh bien, sur la petite fenetre, il y a l'onglet "Memory", et j'ai 8% d'utilisé pour "Data" et 63% d'utilisé pour "Program" :/

    Oui bien sûr ! Je poste ca de suite :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <xc.h>
    #include <pic18f4431.h>
    #include "LCD_6800.h"
    
    //==============================================================================
    // Macro pour générer un pulse sur le E du LCD
    #pragma warning disable 361
    #define LCD_STROBE {LCD_E = 1; __delay_us(5); LCD_E = 0; __delay_us(5);};
    //==============================================================================
    
    //==============================================================================
    // Ecrit une commande
    //==============================================================================
    void LCD_Cmd(char out_char) {
    
        // C/D = 0 => Ecrit une Commande
        LCD_CD = 0;
    
        // 4 bits de poids fort
        LCD_D4 = (unsigned)((out_char & 0x10)?1:0);
        LCD_D5 = (unsigned)((out_char & 0x20)?1:0);
        LCD_D6 = (unsigned)((out_char & 0x40)?1:0);
        LCD_D7 = (unsigned)((out_char & 0x80)?1:0);
        LCD_STROBE 
                
        // 4 bits de poids faible
        LCD_D4 = (unsigned)((out_char & 0x01)?1:0);
        LCD_D5 = (unsigned)((out_char & 0x02)?1:0);
        LCD_D6 = (unsigned)((out_char & 0x04)?1:0);
        LCD_D7 = (unsigned)((out_char & 0x08)?1:0);
        LCD_STROBE
    
        if(out_char == 0x01)__delay_ms(2);
    }
    
    //==============================================================================
    // Défini la position courante du curseur
    //==============================================================================
    void LCD_Set_Cursor(char Ligne, char colonne) {
    
        switch(Ligne){
            case 0: LCD_Cmd((char)(0x80 + 0x00 + (colonne))); break; // Ligne 1
            case 1: LCD_Cmd((char)(0x80 + 0x20 + (colonne))); break; // Ligne 2
            case 2: LCD_Cmd((char)(0x80 + 0x40 + (colonne))); break; // Ligne 3
            case 3: LCD_Cmd((char)(0x80 + 0x60 + (colonne))); break; // Ligne 4
        }             
    }
    
    //==============================================================================
    // Ecrit un caractère à la position courante
    //==============================================================================
    void LCD_Putc(char out_char) {
    
        // C/D = 1 => Ecrit une donnée
        LCD_CD = 1;
    
        // 4 bits de poids fort
        LCD_D4 = (unsigned)((out_char & 0x10)?1:0);
        LCD_D5 = (unsigned)((out_char & 0x20)?1:0);
        LCD_D6 = (unsigned)((out_char & 0x40)?1:0);
        LCD_D7 = (unsigned)((out_char & 0x80)?1:0);
        LCD_STROBE
    
        // 4 bits de poids faible
        LCD_D4 = (unsigned)((out_char & 0x01)?1:0);
        LCD_D5 = (unsigned)((out_char & 0x02)?1:0);
        LCD_D6 = (unsigned)((out_char & 0x04)?1:0);
        LCD_D7 = (unsigned)((out_char & 0x08)?1:0);    
        LCD_STROBE
    }
    
    //==============================================================================
    // Ecrit une chaîne de caractère à partir de la position courante
    //==============================================================================
    void LCD_putrs(char *text) {
        while(*text) LCD_Putc(*text++);
    }
    
    //==============================================================================
    // Initialise le LCD
    //==============================================================================
    void LCD_Init() {
      
        TRISD   = 0; // PORTD en sortie    
    
        LCD_CD  = 0; // Tous les bits à 0
        LCD_E   = 0;
        LCD_D4  = 0;
        LCD_D5  = 0;
        LCD_D6  = 0;
        LCD_D7  = 0;   
        LCD_RST = 1; // RESET à 1 pour activer le LCD
        
        __delay_ms(1);//delay
    
        LCD_Cmd(0x2A);//function set (extended command set)
        LCD_Cmd(0x71);//function selection A
        LCD_Putc(0x00);// disable internal VDD regulator (2.8V I/O). data(0x5C) = enable regulator (5V I/O)
        LCD_Cmd(0x28);//function set (fundamental command set)
        LCD_Cmd(0x08);//display off, cursor off, blink off
        LCD_Cmd(0x2A);//function set (extended command set)
        LCD_Cmd(0x79);//OLED command set enabled
        LCD_Cmd(0xD5);//set display clock divide ratio/oscillator frequency
        LCD_Cmd(0x70);//set display clock divide ratio/oscillator frequency
        LCD_Cmd(0x78);//OLED command set disabled
        LCD_Cmd(0x09);//extended function set (4-lines)
        LCD_Cmd(0x06);//COM SEG direction
        LCD_Cmd(0x72);//function selection B
        LCD_Putc(0x00);//ROM CGRAM selection
        LCD_Cmd(0x2A);//function set (extended command set)
        LCD_Cmd(0x79);//OLED command set enabled
        LCD_Cmd(0xDA);  //set SEG pins hardware configuration
        LCD_Cmd(0x10);//set SEG pins hardware configuration
        LCD_Cmd(0xDC);//function selection C
        LCD_Cmd(0x00);//function selection C
        LCD_Cmd(0x81);//set contrast control
        LCD_Cmd(0x7F);//set contrast control
        LCD_Cmd(0xD9);//set phase length
        LCD_Cmd(0xF1);//set phase length
        LCD_Cmd(0xDB);//set VCOMH deselect level
        LCD_Cmd(0x40);//set VCOMH deselect level
        LCD_Cmd(0x78);//OLED command set disabled
        LCD_Cmd(0x28);//function set (fundamental command set)
        
        LCD_Clear();   //clear display    
        LCD_Cmd(_LCD_TURN_ON); //display ON    
        LCD_Set_Cursor(1,1);
    
        __delay_ms(100);
    }
    
    //==============================================================================
    // TEST
    //==============================================================================
    
    void Check_Index(){
        if (INDEX == LOW && ARB1 == 0){
            index++;
            if(index > 2){index = 0;}
            if(page == 1 && index > 1){index = 0;}
            ARB1 = 1;
        
            while (INDEX == LOW && tempo < 500){
                __delay_ms(3);
                tempo = tempo++;
            }
    
            if(INDEX == LOW && tempo >= 500){
                switch(page){
                
                    case 0 : page = 1;
                    break;
                    
                    case 1 : page = 0;
                    break;
                }
                tempo = 0;
                index = 0;
                LCD_Clear();
            }//Si on fait un appui long sur le bouton d'index, on change de page
            LCD_Clear();    
        }
        else if (INDEX == HIGH){ARB1 = 0;}
    
        if (index == 0){
            LCD_Set_Cursor(1,0);
            LCD_putrs("*");
        }
        else if (index == 1){
            LCD_Set_Cursor(2,0);
            LCD_putrs("*");
        }
        else if (index == 2){
            LCD_Set_Cursor(3,0);
            LCD_putrs("*");
        }
    
    
    }//Fonction pour savoir ou l'on est dans l'index.
    
    
    void main(){
        LCD_Init();
        LCD_Cmd(_LCD_CURSOR_OFF);
        LCD_Clear();
        
        while(1){
            if (page == 0){ //la variable page, sert a changer de page, pour afficher d'autres paramètres
                LCD_Set_Cursor(0,1);
                LCD_putrs("CONSIGNE"); 
                LCD_Set_Cursor(0,10);
                LCD_putrs("/");
                LCD_Set_Cursor(0,13);
                LCD_putrs("MESURE");
    
                sprintf(s, "IDC= %d", IDC);    
                LCD_Set_Cursor(1,1);
                LCD_putrs(s);        
                LCD_Set_Cursor(1,10);
                LCD_putrs("/");        
                sprintf(s, "%d", IDC);    
                LCD_Set_Cursor(1,12);
                LCD_putrs(s);
                LCD_Set_Cursor(1,18);
                LCD_putrs("A");
    
                sprintf(s, "IAC= %d", IAC);    
                LCD_Set_Cursor(2,1);
                LCD_putrs(s);        
                LCD_Set_Cursor(2,10);
                LCD_putrs("/");        
                sprintf(s, "%d", IAC);    
                LCD_Set_Cursor(2,12);
                LCD_putrs(s);  //Texte à display de base.      
                LCD_Set_Cursor(2,18);
                LCD_putrs("A");
    
                sprintf(s, "Frq= %d", Frq);    
                LCD_Set_Cursor(3,1);
                LCD_putrs(s);               
                LCD_Set_Cursor(3,10);
                LCD_putrs("Hz");        
    
                Check_Index();
    
                if (PLUS == LOW && ARB2 == 0){                               
                    if(index == 0){
                        IDC = IDC++;
                        if (IDC > 20){IDC = 20;}
                    }
                    else if(index == 1){
                        IAC = IAC++;
                        if (IAC > 100){IAC = 100;}
                    }
                    else if(index == 2){
                        Frq = Frq++;
                        if (Frq > 100){Frq = 100;}
                    }
                ARB2 = 1;
                }//Lorsque l'on appuie sur RB0, on check sur quel index l'on se trouve, et on incrémente en fonction.         
                else if (PLUS == HIGH && MOINS == HIGH && INDEX == HIGH){
                    ARB2 = 0;
                    tempo = 0;
                }//Lorsque le bouton RB0 est relaché, RAZ des variables.
    
        //******************************************        
            if (PLUS == LOW && tempo < 10){
            __delay_ms(100);
            tempo = tempo++;
            }
            if(PLUS == LOW && tempo >=10){
                if(index == 0){
                    IDC = IDC++;
                    __delay_ms(150);
                    if (IDC > 20){IDC = 20;}
                }
                else if(index == 1){
                    IAC = IAC++;
                    __delay_ms(100);
                    if (IAC > 100){IAC = 100;}
                }
                else if(index == 2){
                    Frq = Frq++;
                    __delay_ms(100);
                    if (Frq > 100){Frq = 100;}
                }   
            }
        //****************************************** //Détection d'un appui long sur le bouton d'incrémentation
                                                     //Cela permet d'incrémenter lorsque l'on laisse appuyer au bout de X secondes
            if (MOINS == LOW && ARB3 == 0){                             
                if(index == 0){
                    IDC = IDC--;
                    if(IDC == 9 || IDC == 99)LCD_Clear();
                    if(IDC < 0){IDC = 0;}
                }
                else if(index == 1){
                    IAC = IAC--;
                    if(IAC == 9 || IAC == 99)LCD_Clear();
                    if (IAC < 0){IAC = 0;}
                }
                else if(index == 2){
                    Frq = Frq--;
                    if(Frq == 9 || Frq == 99)LCD_Clear();
                    if (Frq < 5){Frq = 5;}
                }
            ARB3 = 1;
            }//Lorsque l'on appuie sur RB1, on check sur quel index l'on se trouve, et on décrémente en fonction.         
            else if (MOINS == HIGH && PLUS == HIGH && INDEX == HIGH){
                ARB3 = 0;
                tempo = 0;
            }//Lorsque le bouton RB1 est relaché, RAZ des variables de tembo et ARB.
    
        //******************************************        
            if (MOINS == LOW && tempo < 10){
                __delay_ms(100);
                tempo = tempo++;
            }
            if(MOINS == LOW && tempo >=10){
                if(index == 0){
                    IDC = IDC--;            
                    __delay_ms(150);
                    if(IDC == 9 || IDC == 99)LCD_Clear();
                    if (IDC < 0){IDC = 0;}
                }
                else if(index == 1){
                    IAC = IAC--;           
                    __delay_ms(100);
                    if(IAC == 9 || IAC == 99)LCD_Clear();
                    if (IAC < 0){IAC = 0;}
                }
                else if(index == 2){
                    Frq = Frq--;           
                    __delay_ms(100);
                    if(Frq == 9 || Frq == 99)LCD_Clear();
                    if (Frq < 5){Frq = 5;}
                }
            }   
        //****************************************** //Détection d'un appui long sur le bouton de décrémentation
                                                     //Cela permet de décrémenter lorsque l'on laisse appuyer au bout de X secondes
    
        
        }
        
            if (page == 1){
                LCD_Set_Cursor(0,1);
                LCD_putrs("Reglages du P.I.D"); 
                
                sprintf(s, "Kp= %3.3f", Kp);    
                LCD_Set_Cursor(1,1);
                LCD_putrs(s);
                
                sprintf(s, "Coeff A= %3.3f", Coeff);    
                LCD_Set_Cursor(2,1);
                LCD_putrs(s);
    
                Check_Index();
                
                    if (PLUS == LOW && ARB2 == 0){                               
                        if(index == 0){
                            Kp = Kp+ 0.1;
                            if (Kp > 5){Kp = 5;}
                        }
                        else if(index == 1){
                            Coeff = Coeff + 0.1;
                            if (Coeff > 5){Coeff = 5;}
                        }
                    
                ARB2 = 1;
                }//Lorsque l'on appuie sur RB0, on check sur quel index l'on se trouve, et on incrémente en fonction.         
                else if (PLUS == HIGH && MOINS == HIGH && INDEX == HIGH){
                    ARB2 = 0;
                    tempo = 0;
                }//Lorsque le bouton RB0 est relaché, RAZ des variables.
    
        //******************************************        
            if (PLUS == LOW && tempo < 10){
            __delay_ms(100);
            tempo = tempo++;
            }
            if(PLUS == LOW && tempo >=10){
                if(index == 0){
                    Kp = Kp + 0.1;
                    __delay_ms(150);
                    if (Kp > 5){Kp = 5;}
                }
                else if(index == 1){
                    Coeff = Coeff + 0.1;
                    __delay_ms(100);
                    if (Coeff > 5){Coeff = 5;}
                }
      
            }
            if (MOINS == LOW && ARB3 == 0){                             
                if(index == 0){
                    Kp = Kp - 0.1;
                    if(Kp < 0){Kp = 0;}
                }
                else if(index == 1){
                    Coeff = Coeff - 0.1;
                    if (Coeff < 0){Coeff = 0;}
                }
                ARB3 = 1;
            }//Lorsque l'on appuie sur RB1, on check sur quel index l'on se trouve, et on décrémente en fonction.         
            else if (MOINS == HIGH && PLUS == HIGH && INDEX == HIGH){
                ARB3 = 0;
                tempo = 0;
            }//Lorsque le bouton RB1 est relaché, RAZ des variables de tembo et ARB.
    
        //******************************************        
            if (MOINS == LOW && tempo < 10){
                __delay_ms(100);
                tempo = tempo++;
            }
            if(MOINS == LOW && tempo >=10){
                if(index == 0){
                    Kp = Kp - 0.1;;            
                    __delay_ms(150);
                    if (Kp < 0){Kp = 0;}
                }
                else if(index == 1){
                    Coeff = Coeff - 0.1;           
                    __delay_ms(100);
                    if (Coeff < 0){Coeff = 0;}
                }
    
            }
            }
        }
        }
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

  4. #4
    jiherve

    Re : Alternative à la commande "sprintf"

    bonsoir,
    sprintf est tellement générique et paramétrable que c'est un gros bout de code;
    La solution c'est de développer ou de récupérer une routine assembleur qui fait la même chose mais juste pour les entiers.
    JR
    l'électronique c'est pas du vaudou!

  5. A voir en vidéo sur Futura
  6. #5
    dje8269

    Re : Alternative à la commande "sprintf"

    Bonsoir,

    Ce n'est pas la fonction "sprintf " réellement qui est en cause mais le texte que tu lui indiques d’afficher . Tout le texte que tu mets entre guillemets pour le passer en argument a la fonction sprintf est mis en ROM .

    Il faudrait que tu créer un tableau pour accueillir ton texte.
    Ensuite tu remplis ce tableau avec ton texte , ainsi le texte est mis en RAM et ne coute en espace mémoire que l'allocation de ton tableau.
    Et ensuite tu affiches ton tableau ( qui contient ton texte mis dedans juste avant) .

    ce devrait ressembler a quelques choses comme ca
    C'est en faisant des erreurs; que l'on apprend le mieux !!

  7. #6
    lou_ibmix_xi

    Re : Alternative à la commande "sprintf"

    Ce n'est pas la fonction "sprintf " réellement qui est en cause mais le texte que tu lui indiques d’afficher . Tout le texte que tu mets entre guillemets pour le passer en argument a la fonction sprintf est mis en ROM .
    Je suis d'accord.

    J'ajoute que normalement en flash la fonction sprintf n'occupe qu'une seule fois l'espace mémoire nécessaire, que tu l'appelles 1 fois ou 100 fois dans ton code c'est pareil.

    Un gros détail, je ne connais pas le PIC, mais si il n'a pas d'unité flottante, et que sprintf gère la conversion des flottants, il te tire l'émulateur logiciel qui doit faire son poids. Il est parfois possible d'inhiber cette fonctionalitée. Mais attention également à n'utiliser AUCUN flottant!

    Au pire, une fonction de conversion faite maison est relativement simple à faire, tout en étant un bon exercice...

  8. #7
    jiherve

    Re : Alternative à la commande "sprintf"

    Bonsoir,
    un peu de lecture :https://www.avrfreaks.net/forum/dstr...uction-sprintf
    Bien sur ce n'est pas du PIC mais cela ne doit pas être très éloigné au niveau code assembleur (cependant les PIC sont plus lourds que les Atmel car leur adressage est paginé si mes souvenirs sont bons)
    les "messages" ne demandent qu'un octet par caractère le code lui est sans commune mesure!
    JR
    l'électronique c'est pas du vaudou!

  9. #8
    Jack
    Modérateur

    Re : Alternative à la commande "sprintf"

    Citation Envoyé par tomjcb Voir le message
    (PS : J'ai bien évidemment fais quelques recherches, et j'ai trouvé une fonction appelée "itoa", mais je n'arrive pas du tout à la mettre en application ...)
    Quel problème rencontres-tu lors de l'utilisation de itoa? Cette fonction me semble pourtant plus simple syntaxiquement que sprintf.

  10. #9
    pm42

    Re : Alternative à la commande "sprintf"

    Et en cherchant un peu, on trouve facilement des implémentations en quelques lignes de C de la conversion int -> string.
    Suivant le genre de gestion de la mémoire, de taille des entiers, de support des nombres négatifs ou pas, c'est plus ou moins compliqué mais jamais vraiment beaucoup.

  11. #10
    tomjcb

    Re : Alternative à la commande "sprintf"

    Tout d'abord, bonjour à vous tous et merci de vos nombreuses réponses.

    Alors en effet, dans le code j'utilise 2 sprintf qui gère des flottants, j'ai simplement enlevé ces deux lignes de sprintf, et, magie, on enlève environ 30% d'occupation de mémoire, je ne pensais pas que ca pouvait etre aussi gourmand ...

    Et pour ce qui est de la fonction itoa, j'ai trouvé un exemple sur internet qui ressemble a ca :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main()
    {
        int a=54325;
        char buffer[20];
        itoa(a,buffer,2);   // here 2 means binary
        printf("Binary value = %s\n", buffer);
     
        itoa(a,buffer,10);   // here 10 means decimal
        printf("Decimal value = %s\n", buffer);
     
        itoa(a,buffer,16);   // here 16 means Hexadecimal
        printf("Hexadecimal value = %s\n", buffer);
        return 0;
    }
    J'ai donc ajouté une ou deux lignes adaptées a mes fonctions pour afficher quelque chose de simple pour le LCD, j'ai procédé comme ceci :
    Code:
    int main()
    {
        int a=54325;
        char buffer[20];
        itoa(a,buffer,10);   // here 10 means decimal
        printf("Binary value = %s\n", buffer);
        LCD_putrs(buffer)
    
        return 0;
    }
    Par contre je n'ai pas bien compris l'utilité du printf dans l'exemple que j'ai trouvé..
    De ce que j'ai compris, la fonction itoa(), prend comme paramètres, le int que l'on veut mettre en forme de string, la variable dans laquelle va être stockée la forme convertie, et enfin la base, pour savoir si on est en binaire, héxa, ou bien décimal.

    Mais lorsque, suite à ça, j'utilise la commande LCD_putrs, pour écrire sur le LCD, il n'y a absolument rien qui s'affiche, peut etre que je m'y prends mal ou alors que je n'ai pas du tout compris son fonctionnement.

    Bien à vous, Tom
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

  12. #11
    Seb.26

    Re : Alternative à la commande "sprintf"

    <my 2 cents>
    Perso pour convertir un uint**_t en char[] je fais toujours un truc perso du genre :
    Code:
    /!\ pseudo-code à adapter !!! /!\
    uint16_str(uint16_t val, char[] resultat)
    {
      resultat[0] = 0;
      tantque(val>10000)
        resultat[0]++
        val = val-10000
    
      resultat[1] = 0;
      tantque(val>1000)
        resultat[1]++
        val = val-1000
    
      ..etc...
    }
    Tu peux aussi ajouter des options comme "remplir de 0 ou pas le résultat", "indenter ou pas" ...etc... c'est rapide et pas cher en ROM/RAM ...

    Quand à utiliser des float dans un uCPU ... ... est-ce vraiment utile ?? ... des virgules flottantes ne seraient elles pas suffisantes ?
    Dernière modification par Seb.26 ; 18/05/2018 à 09h54.
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  13. #12
    tomjcb

    Re : Alternative à la commande "sprintf"

    Ahh d'accord je crois que je vois comment faire.

    Et pour ce qui est des float et des virgules flottantes .... ce n'est pas la même chose ? J'ai toujours pensé que cela voulait dire pareil ... ^^'
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

  14. #13
    Seb.26

    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  15. #14
    Seb.26

    Re : Alternative à la commande "sprintf"

    Citation Envoyé par tomjcb Voir le message
    Et pour ce qui est des float et des virgules flottantes .... ce n'est pas la même chose ?
    Quand ton cerveau pense un truc et que tes mains écrivent le contraire ... ... je pensais évidement aux virgules fixes ...
    (car oui, les float sont justement des virgules flottantes ...)
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  16. #15
    pm42

    Re : Alternative à la commande "sprintf"

    Ca, c'est sur la virgule fixe. Plus haut, tu parlais de virgule flottante en l'opposant au type float.

  17. #16
    jiherve

    Re : Alternative à la commande "sprintf"

    Bonjour,
    Le codage des flottants n'est pas stricto sensu un codage binaire en virgule flottante car elle est de facto fixe située entre le bit 23 et le bit 22(avec un 1 implicite devant pour les non dénormalisés et un codage 32 bits), il y a par contre un exposant. Une virgule flottante stricto sensu c'est autre chose, cela signifie que par exemple sur un codage en 32bits la position de la virgule peut se balader d'un bout à l'autre du nombre la seule constante étant que le nombre de bits destinés au codage de la partie entière + le nombre de bits codants la partie fractionnaire vaut toujours 32.
    On parle alors de codage I.F ou I est le nombre de bits entiers et F le nombre de bits fractionnaires.
    Il est assez difficile de calculer en virgule flottante car il faut ajuster la position de cette virgule en fonction des calculs effectués.
    JR
    l'électronique c'est pas du vaudou!

  18. #17
    Jack
    Modérateur

    Re : Alternative à la commande "sprintf"

    Citation Envoyé par tomjcb Voir le message
    Et pour ce qui est de la fonction itoa, j'ai trouvé un exemple sur internet qui ressemble a ca :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main()
    {
        int a=54325;
        char buffer[20];
        itoa(a,buffer,2);   // here 2 means binary
        printf("Binary value = %s\n", buffer);
     
        itoa(a,buffer,10);   // here 10 means decimal
        printf("Decimal value = %s\n", buffer);
     
        itoa(a,buffer,16);   // here 16 means Hexadecimal
        printf("Hexadecimal value = %s\n", buffer);
        return 0;
    }
    Par contre je n'ai pas bien compris l'utilité du printf dans l'exemple que j'ai trouvé..
    le printf est là pour afficher le résultat de la conversion.

    De ce que j'ai compris, la fonction itoa(), prend comme paramètres, le int que l'on veut mettre en forme de string, la variable dans laquelle va être stockée la forme convertie, et enfin la base, pour savoir si on est en binaire, héxa, ou bien décimal.
    L'idéal est de lire la doc du compilateur XC8:
    ITOASynopsis
    #include <stdlib.h>
    char * itoa (char * buf, int val, int base)
    Description
    The function itoa converts the contents of val into a string which is stored into buf.
    The conversion is performed according to the radix specified in base. buf is assumed
    to reference a buffer which has sufficient space allocated to it.
    Example
    #include <stdlib.h>
    #include <stdio.h>
    void
    main (void)
    {
    char buf[10];
    itoa(buf, 1234, 16);
    printf("The buffer holds %s\n", buf);
    }
    See Also
    strtol(), utoa(), ltoa(), ultoa()
    Return Value
    This routine returns a copy of the buffer into which the result is written.
    Tu pourras constater que tu a inversé la position des 2 premiers paramètres de la fonction, c'est à dire la chaine et l'entier.

  19. #18
    tomjcb

    Re : Alternative à la commande "sprintf"

    Alors tout d'abord, bonjour à tous, et merci encore une fois de vos nombreuses réponses.

    Je suis allé voir la documentation concernant la virgule fixe, et en effet ca soulagerait surement le système des deux floats que j'utilise.
    Par contre je ne pense pas avoir saisit complètement comment on les utilise, mais en testant et en me documentant davantage.
    Je crois comprendre qu'on utilise le décalage de bit.


    Et pour ce qui est de la commande itoa(), je n'avais pas du tout remarqué l'inversion de paramètres, il faudrait que j'essaye donc avec les paramètres aux bons endroits
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

  20. #19
    lou_ibmix_xi

    Re : Alternative à la commande "sprintf"

    Je suis allé voir la documentation concernant la virgule fixe, et en effet ca soulagerait surement le système des deux floats que j'utilise.
    Par contre je ne pense pas avoir saisit complètement comment on les utilise, mais en testant et en me documentant davantage.
    Je crois comprendre qu'on utilise le décalage de bit.
    Il faut imaginer ton nombre comme étant écrit "N x 2^(-q)", N est ton entier et q est le nombre de bits après la virgule que tu choisis. Un exemple, avec 10bits après la virgule:
    Code:
    int x = 12345; // en fait 12345/1024
    int y = 12; // en fait 12/1024
    int z = x * y * 1024; // c'est bien x * y puisque x*2^n * y*2^n = x*y * 2^(2n), il faut diviser par 2^n pour retourner dans la bonne dynamique
    Ceci dit, la virgule fixe n'est pas forcément la solution la plus adaptée à ton problème, tu peux peut-être gérer partie entière / partie décimale dans 2 variables séparées.
    Il n'y a pas de é"meilleur solution", seulement une solution mieux adaptée à ton problème.

  21. #20
    tomjcb

    Re : Alternative à la commande "sprintf"

    Bonjour à toi, effectivement j'ai bricolé de mon côté et c'est ce que j'ai fait, avec deux variables pour une partie entière et l'autre pour la décimal, (donc exemple, au lieu de ma variable Kp, j'ai maintenant KpG et KpD qui représente les parties "gauche" (avant la virgule) et "droite" (après la virgule).

    Donc pour ce qui est de l'affichage, tout va bien je n'ai plus à utiliser un sprintf avec un float qui me bouffait beaucoup trop de place.

    Mais un autre léger soucis vient se joindre.

    En effet, il faut que je puisse réutiliser cette variable "coupée en deux", par exemple la, il faut que je renvoie mon Kp au correcteur PID, j'ai donc essayé de le remttre sous forme dite "normale", voila comment j'ai procédé :

    ((KpG * 100) + KpD) / 100.

    Donc par exemple, imaginons qu'on a 1,25
    On se retrouve alors avec KpG = 1 et KpD = 25

    Donc normalement si on suit l'opération :

    1*100 =100
    100 + 25 = 125
    125 / 100 = 1.25

    Je me retrouve bien normalement par le calcul avec ma valeur a virgule.
    Or, j'ai affichée la valeur calculée (avec un sprintf + float, juste pour voir si la valeur est bien calculée), et par exemple, si on a 1.25, il y aura juste affiché 1.000

    Voila je voulais donc savoir si mon raisonnement était bon, et ou se trouve mon erreur

    En vous remerciant d'avance, Tom
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

  22. #21
    Seb.26

    Re : Alternative à la commande "sprintf"

    Citation Envoyé par tomjcb Voir le message
    125 / 100 = 1.25
    Si c'est des int, 125/100 = 1 ... pas de virgule ... tu dois faire m'affichage en fonction ...

    PS: *100 et /100 c'est galère pour le CPU, c'est pour ça qu'on utilise des virgules fixes en puissance de deux ...
    Dernière modification par Seb.26 ; 22/05/2018 à 13h06.
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  23. #22
    tomjcb

    Re : Alternative à la commande "sprintf"

    Effectivement j'ai enfin trouvé mon erreur .. mais c'est vrai que c'est galère pour le CPU, je vais essayer de changer tout ca en virgule fixe ! Merci en tout cas pour vos nombreuses réponses vous m'avez beaucoup aidé !
    Je ne pense pas qu'il y est de bonnes ou de mauvaises situations...

Discussions similaires

  1. probleme fonction "sprintf" sur pic18 et 18f4550
    Par inviteac751535 dans le forum Électronique
    Réponses: 4
    Dernier message: 19/02/2012, 17h47
  2. Choix sur une source d'énergie alternative "economiquement" réalisable en auto construction
    Par invitecd24b5cc dans le forum Habitat bioclimatique, isolation et chauffage
    Réponses: 22
    Dernier message: 25/04/2011, 22h53
  3. Fonction " sprintf " et LCD sur ATMEL
    Par Poseidon88 dans le forum Électronique
    Réponses: 7
    Dernier message: 23/02/2011, 16h13
  4. Chauffage : quelle "alternative" choisir?
    Par inviteda9f4bfc dans le forum Habitat bioclimatique, isolation et chauffage
    Réponses: 5
    Dernier message: 03/04/2008, 12h19
Découvrez nos comparatifs produits sur l'informatique et les technologies.