[Programmation] PIC16F877 et ecran LCD 2*16
Répondre à la discussion
Affichage des résultats 1 à 17 sur 17

PIC16F877 et ecran LCD 2*16



  1. #1
    invite379c0cd7

    PIC16F877 et ecran LCD 2*16


    ------

    Bonjour à tous, Voici c'est ce que je veux faire:
    je veux afficher un nombre en fonction de la tension sur l'entrée analogique RA0 mais celle -ci selon la valeur sur RA1.le code est sans erreur mais affiche des fausses valeurs je crois.Un peu d'aide est le bienvenu.Merci

    Code:
    sbit LCD_RS at RB0_bit;
    sbit LCD_EN at RB1_bit;
    sbit LCD_D4 at RB2_bit;
    sbit LCD_D5 at RB3_bit;
    sbit LCD_D6 at RB4_bit;
    sbit LCD_D7 at RB5_bit;
    
    sbit LCD_RS_Direction at TRISB0_bit;
    sbit LCD_EN_Direction at TRISB1_bit;
    sbit LCD_D4_Direction at TRISB2_bit;
    sbit LCD_D5_Direction at TRISB3_bit;
    sbit LCD_D6_Direction at TRISB4_bit;
    sbit LCD_D7_Direction at TRISB5_bit;
    
    
    
    
    void main() 
    {
         float temp_res,Vc;
         char *sortie[8];
          char *out[8];
       
       Lcd_Init();
       Lcd_Cmd(_LCD_CLEAR);               // Clear display
       Lcd_Cmd(_LCD_CURSOR_OFF);
      
      Adc_init();
      
      TRISA  = 0xFF;  // programmtion du PORTA en entrée
      TRISD  = 0xFF;
      TRISB  = 0;         // programmtion du PORTB en sortie
      
        do 
           {
      adcon0=0x80;
    
                  temp_res = ADC_Read(0)*5.0/1024;   // Get 10-bit results of AD conversion in RA0
               
    
                  Vc = ADC_Read(1)*5.0/1024;   // Get 10-bit results of AD conversion in RA1
                
                      if (0 < Vc < 1)
                       {
                        temp_res= temp_res*temp_res/377;
                        FloatToStr(temp_res,sortie);
                        Lcd_Out(1, 1, sortie);
                        Delay_ms(100) ;
                       }
                      if (1 <= Vc < 2.8)
                       {
                        FloatToStr(temp_res,sortie);
                        Lcd_Out(1, 7, sortie);
                        Delay_ms(100) ;
                       }
                      if (2.8<= Vc < 5)
                       {
                        temp_res= temp_res/377;
                        FloatToStr(temp_res,sortie);
                        Lcd_Out(2, 1, sortie);
                        Delay_ms(100) ;
                       }
    
       Delay_ms(100) ;
    
           }
         while(1);
    }

    -----
    Images attachées Images attachées
    Fichiers attachés Fichiers attachés
    Dernière modification par Antoane ; 17/07/2019 à 08h33. Motif: Intégration du code au corps du message

  2. #2
    invitef86a6203

    Re : PIC16F877 et ecran LCD 2*16

    Tu es sur de ta syntaxe ?
    if (0 < Vc < 1)
    Évidement ça dépend du compilateur...

    Généralement on écrit comme ça:
    if ( (Vc>0) && (Vc<1) )

  3. #3
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    Et qu'est ce que je fais pour qu’il affiche seulement un nombre à 2 chiffres apres la virgule.Cordialement.

  4. #4
    tchitchou

    Re : PIC16F877 et ecran LCD 2*16

    Arrondir à 2 décimales, ptet ?

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

    Re : PIC16F877 et ecran LCD 2*16

    comment faire pour arrondir à 2 decimal près.je connais peu de chose sur la programmation surtout sur les PIC

  7. #6
    paulfjujo

    Re : PIC16F877 et ecran LCD 2*16

    bonjour


    soit utiliser une autre fonction pour convertir le float en ascii
    soit utiliser floor

    Code:
    void Float2Ascii (float x, unsigned char *str,char precision)
    {
     // converts a floating point number to an ascii string
     // version limitée à 5 decimales maximum
     // x is stored into str, which should be at least 30 chars long
     int ie, i, k, ndig;
     double y;
     if (precision>=5) precision=5;  else precision++;
     ndig =   precision;
    
     ie = 0;
     // if x negative, write minus and reverse
     if ( x < 0.00000)
     {
       *str++ = '-';
       x = -x;
     }
     // put x in range 1 <= x < 10
     if (x > 0.000000) while (x < 1.000000)
     {
       x *= 10.000;                // a la place de =*
       ie--;
     }
     while (x >= 10.0000)
     {
       x = x/10.0000;
       ie++;
     }
     // in f format, number of digits is related to size
     ndig += ie;                                // a la place de =+
     //round. x is between 1 and 10 and ndig will be printed to
     // right of decimal point so rounding is ...
     for (y = i = 1; i < ndig; i++)
     y = y/10.0000;
     x += y/2.0000;
     if (x >= 10.0000) {x = 1.0000; ie++;}
     if (ie<0)
     {
       *str++ = '0'; *str++ = '.';
       if (ndig < 0) ie = ie-ndig;
       for (i = -1; i > ie; i--)  *str++ = '0';
     }
     for (i=0; i < ndig; i++)
     {
       k = x;
       *str++ = k + '0';
       if (i ==  ie ) *str++ = '.';
       x -= (y=k);
       x *= 10.0000;
      }
     *str = '\0';
    }
    
    
     
     //Precision d'affichage à limiter à 7 decimales maxi !
     //avec calcul flottant en simple precision 32 bits
      
    float F1;
    char CRam[30];
    .....
    
        CRLF();
       F1=3.14159265359;
         Float2Ascii (F1,CRam1,8);
        UART1_Write_Text(CRam1);
        CRLF();
        
       F1=  0.9996012717 ;
       Float2Ascii (F1,CRam1,8);
        UART1_Write_Text(CRam1);
        CRLF();
       while(1);
       
    Resultat:
    3.1415927
    0.9996012
    ----------------------------
    Float2Ascii (F1,CRam1,2);
     pour avoir
    3.14
    et 
    0.99 
    
    
    ----------------------------------------------------------
    ou alors
    
    float F1,F2;
    char CRam[20];
    
    mise en forme resultat
    
       for (F1=0.0;F1<65.0;F1=F1+0.25)
       {
       F2=floor(F1 * 100.0);
                     k=(unsigned int)F2;
                     WordToStr(k,CRam1);
                     k=strlen(CRam1);
                     *(CRam1+k+1)=0;
                     *(CRam1+k)= *(CRam1+k-1);
                     *(CRam1+k-1)= *(CRam1+k-2);
                     *(CRam1+k-2)='.';
                     if (*(CRam1+k-1)==' ') *(CRam1+k-1)='0';
                     if (*(CRam1+k-3)==' ') *(CRam1+k-3)='0';
                     UART1_Write_Text(CRam1);
                     CRLF1();
          }
          while(1);
      0.00
      0.25
      0.50
      0.75
      1.00
      1.25
      1.50 
     63.25
     63.50
     63.75
     64.00
     64.25
     64.50
     64.75
    Dernière modification par Antoane ; 18/07/2019 à 17h24. Motif: remplacement des balises quote par code, cf. https://forums.futura-sciences.com/showthread.php?p=5889620

  8. #7
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    Merci beaucoup, mais une petite question.quand j'affiche un nombre >1 ça marche bien mais quand le nombre est entre 0 et 1,il affiche un nombre bizzare comme il ne reconnait pas la virgule.

  9. #8
    invitef86a6203

    Re : PIC16F877 et ecran LCD 2*16

    char *sortie[8];
    FloatToStr(temp_res,sortie);


    Tu déclare un tableau de pointeur et tu écris par rapport au pointeur de ce tableau de pointeur.

    "ça doit lui faire mal aux dents !!!!!!!"


    char sortie[8];
    FloatToStr(temp_res,sortie);
    serait mieux...

    De plus 7 char (le 8 ièm c'est le '\0') pour une telle conversion c'est vraiment risqué !

    char sortie[20];
    FloatToStr(temp_res,sortie);
    Plus sur mais avec un pic16F877 la mémoire est limitée...

    La méthode paulfjujo est plus adaptée à ce pic16f.



    char *out[8];
    Même chose !

  10. #9
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    merci tout le monde de votre aide.

  11. #10
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    pardon, mais quand j'entre une valeur < 25mV la fonction Float2Ascii ne donne pas la valeur desirée. un peu d'aide d'il vous plait

  12. #11
    paulfjujo

    Re : PIC16F877 et ecran LCD 2*16

    bonjour

    la fonction FloatToAscii n'a rien à voir avec ce probleme
    ou si peu

    le flottant MikroC est sur 32 bits seulement,
    la representaion en flottant devient limite avec par exemple
    la representation de 0,001 avec 3 decimales -> donne 0.00
    mais 0,0011 donne -> 0.001
    dans les autres cas c'est correct , voir code et resultat

    Ton probleme est que tu fait une division en entier avec ADC* 5/1024
    2 amelioration possibles
    * Predefinir la mise à l'echelle 5.0/1024.0 => 0.0048828125 arrondi à 0.004883
    pas la peine de trainer des decimales au dela de 7 !
    * caster la mesure de l'ADC ( entier 16 bits ) en flotant
    float F1;

    nota: bien rajouter le . (point) apres les valeurs lorsqu'on initialise des donnees en flottant.
    Le compilateur manipule alors des flottants au lieu d'entier .
    5.00

    ex: F1 = (float)ADC_Read(0);
    pour le mutiplier ensuite avec le facteur d'echelle
    temp_res = F1* 0.004883;
    (on peut le faire aussi dans la foulée : temp_res=(float)ADC_Read(0) * 0.004883

    voir les resultats correspondant aux differentes façon de coder
    avec ADC=1 on obtient 0.005


    --- avec Float2Ascii------------
    F1=0.001 3 decimales-> 0.00
    F1=0.0011 3 decimales -> 0.001
    F1=0.005 3 decimales-> 0.005
    F1=0.015 3 decimales -> 0.015
    F1=0.150 3 decimales-> 0.150
    F1=15 3 decimales -> 15.000
    F1=1.234 3 decimales ->1.234
    1) ADC= 5 => resultat en Volts sur 3 decimales -> 0.000
    2) ADC= 5 => resultat en Volts sur 3 decimales -> 0.024
    3) ADC= 5 => resultat en Volts sur 3 decimales -> 0.024
    4) ADC=5 => resultat en Volts sur 3 decimales -> 0.024
    5) ADC=2 => resultat en Volts sur 3 decimales -> 0.01
    6) ADC=1 => resultat en Volts sur 3 decimales -> 0.005
    Code:
     // float F1;
     // char TEXTE[80];  multi usage
     //char *txt;
     
     txt=&TEXTE[0];
     
       UART1_Write_CText(" --- avec Float2Ascii------------\r\n");
       
     F1=0.001 ;
     Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=0.001  3 decimales-> ");
      UART1_Write_Text(txt);
      CRLF1();
      
      F1=0.0011 ;
     Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=0.0011  3 decimales -> ");
      UART1_Write_Text(txt);
      CRLF1();
      
      F1=0.005 ;
     Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=0.005  3 decimales-> ");
      UART1_Write_Text(txt);
      CRLF1();
      
       F1=0.015 ;
       Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=0.015  3 decimales -> ");
      UART1_Write_Text(txt);
        CRLF1();
      
       F1=0.150 ;
     Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=0.150  3 decimales-> ");
      UART1_Write_Text(txt);
        CRLF1();
    
        F1=15;  //mV
     Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=15  3 decimales -> ");
      UART1_Write_Text(txt);
        CRLF1();
    
       F1=1.234;  //V
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" F1=1.234  3 decimales ->");
      UART1_Write_Text(txt);
       CRLF1();
      //K represente la valeur lue par ADC
      k=5;
      F1= k* 5/1024;
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" 1) ADC= 5 => resultat en Volts sur  3 decimales -> ");
      UART1_Write_Text(txt);
       CRLF1();
    
      k=5;
      F1= k* 5.00/1024.0;
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" 2) ADC= 5 => resultat en Volts sur  3 decimales -> ");
      UART1_Write_Text(txt);
       CRLF1();
       
       
      k=5;
      F1= k* 0.004883  ;
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" 3) ADC= 5 => resultat en Volts sur  3 decimales -> ");
      UART1_Write_Text(txt);
       CRLF1();
      
      k=5;
      F1=(float) k* 0.004883    ; // arrondi de 5.0/1024.0 =0.0048828125
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" 4)  ADC=5 => resultat en Volts sur  3 decimales -> ");
      UART1_Write_Text(txt);
       CRLF1();
      
       k=2;
      F1=(float) k* 0.004883    ;
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" 5)  ADC=2 => resultat en Volts sur  3 decimales -> ");
      UART1_Write_Text(txt);
       CRLF1();
       
        k=1;
      F1=(float) k* 0.004883    ;
      Float2Ascii (F1,txt,3) ;
      UART1_Write_CText(" 6)  ADC=1 => resultat en Volts sur  3 decimales -> ");
      UART1_Write_Text(txt);
       CRLF1();
    Dernière modification par paulfjujo ; 20/07/2019 à 13h14.

  13. #12
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    @paulfjujo
    Tu as raison,la fonction FloatToAscii n'a rien à voir avec ce probleme.J'ai suivi tes conseils pour les nombres flottants mais ça ne marche pas encore.
    Avec: temp_res=(float)ADC_Read(0) * 0.004883; pour une entrée de 2.5mV à 7mV ---> 0.0049
    pour une entrée de 8mV à 12mV ----> 0.0098
    pour une entrée de 13mV à 17mV ----> 0.0146
    simulation sur proteus 8.0.
    Merci

  14. #13
    invite5637435c

    Re : PIC16F877 et ecran LCD 2*16

    Bonjour,
    qu'est-ce qui ne fonctionne pas exactement?
    pour une entrée de 2.5mV à 7mV ---> 0.0049
    pour une entrée de 8mV à 12mV ----> 0.0098
    pour une entrée de 13mV à 17mV ----> 0.0146
    Les résultats semblent corrects.
    Dans la réalité les résultats dépendront essentiellement de la qualité du routage et des influences "parasites", des filtrages etc.

  15. #14
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    Bonjour/bonsoir
    Donc c'est normal ces valeurs là?parceque je suis un peu étonné qu'il affiche la même valeur que ce soit 14 ou 15 ou 16 mV.Mais si vous le dites,je ferai avec ça alors.

  16. #15
    paulfjujo

    Re : PIC16F877 et ecran LCD 2*16

    bonsoir,


    l' ADC donne une mesure à +-1 bit soit +-5mV
    avec en plus un possible decalage d'offset à zero .

    Moi je ferai plutot les tests sur la mesure brute en points ,
    (Comparer des entiers )
    plutot que sur la mesure convertie en mV.

    le fait de passer de 1024 points à 5,000mV ne change en rien que le pas de mesure sera à 5mV pres.

    pour plus de resolution, il faut passer avec un PIC ayant un ADC 12 bits ex 18F27K42

  17. #16
    invite5637435c

    Re : PIC16F877 et ecran LCD 2*16

    Ce qui est important également c'est d'utiliser quelques astuces liées à la théorie du signal, comme la décimation par exemple, qui permet d'augmenter le nombre de bits sans changer de µC.
    Exemple: http://genelaix.free.fr/IMG/pdf/canover.pdf
    Utiliser le filtrage numérique également, quitte à avoir un µC autant se servir de tout ce qu'il peut produire pour obtenir un résultat plus pointu.

  18. #17
    invite379c0cd7

    Re : PIC16F877 et ecran LCD 2*16

    OK! je comprends mieux maintenant.merci beaucoup.

Discussions similaires

  1. Pic16f877 c++
    Par invite35b4bb14 dans le forum Électronique
    Réponses: 2
    Dernier message: 09/12/2012, 22h24
  2. PIC16F877 a 25 MHz ...??
    Par invite49060bcb dans le forum Électronique
    Réponses: 24
    Dernier message: 01/05/2011, 17h16
  3. Mli pic16f877
    Par invite3a2a75b6 dans le forum Électronique
    Réponses: 7
    Dernier message: 25/04/2010, 21h46
  4. pic16f877
    Par invite814175e4 dans le forum Électronique
    Réponses: 0
    Dernier message: 16/12/2009, 15h28
  5. ccs pic16f877 PWM
    Par invitefc1671e3 dans le forum Électronique
    Réponses: 0
    Dernier message: 21/09/2007, 04h00
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...