Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

LCD 4x20 I2C Probleme avec Pointeur ,pas clair avec MikroC
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 1684
Âge : 69
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#1 Message par paulfjujo » mer. 22 juil. 2020 18:20

bonjour à tous,


Ce post est en parralelle avec la section ASM sur la gestion LCD 4x20 , mais en I2C

:!!: il est destiné à faire apparaitre de futurs problemes lié à la complexité progressive d'un programme...
où des effets de bords commencent à se manifester.
debordement de page , de bank ...

oops .. en plus des erreurs humaines !

Pour l'instant, en asm, l'ecriture en dur à des adresses bien precises et CONNUES donnent ( :sifflotte: toujours) de bon resultats.
oops En C , on fait confiance au compilateur ...

Suite au rajout de cette fonction dansun programme existant ( pourtant succint!) :

Code : Tout sélectionner


 
// convert int ADC value to a string with 3 decimal =>  0.000 to 5.000 
char * value_converter(unsigned int adc_value)
{
// declaration d'un pointeur sur char
 char *p1;    // with this additional pointer   , OK sur terminal, OK sur LCD
 char T[8];  // local variable table de characteres
 // char *p1;    // with this additional pointer   ,OK sur terminal , BAD sur LCD
  long vout ;
  unsigned int va;
  p1=&T[0]; // initialise la valeur du pointeur
    vout= (long)adc_value * 5000 >>10;
    value = (unsigned int) vout;
       T[0] =  va/1000+48;   //Add 48 to get the ASCII character
       T[1]='.' ;
       T[2] = ( va/100)%10+48;
       T[3] =  (va/10)%10 +48;
       T[4] = ( va %10) +48;
       T[5]=0;
    return p1;     // OK .. but BAD  with return &T[0]; or return T;
} 

... usage

    txt
=&TEXTE[0];
     *(txt)=0;
     txt=value_converter(EA0); // return a pointer
     strcat(txt," V");
     UART1_Write_Text(txt);       //  OK on terminal 
     CRLF1();
     LCD_putcmd(LCD_LINE4,1);     // Bad on LCD if i don't use an additional char pointer inside value_converter(EA0);
     LCD_puts(txt);
     Delay_1sec();





et ensuite utiliser le pointeur resultant avec l'UART ou le LCD
je constate que le comportement differe suivant l'ordre d'initialisation du pointeur situé dans ma fonction!
j'ai ouvert un post la-dessus sur le forum MikroC.

En C traditionnel on pouvait gerer les Far_pointeurs ..(Turbo C2.00) et les manipuler facilement.
sous mikroC on ne sait pas trop comment c'est géré.

dans l'ASM généré par le compilo

Code : Tout sélectionner

_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0722.c,694 ::                 char value_converter(unsigned int adc_value)
char value_converter(unsigned int adc_value)
{
  
char p1;    // with this additional pointer   , OK sur LCD  if declared first
  
char T[8];  // local variable
  
long vout ;
  
unsigned int value;
  
p1=&T[0]; 


donne

;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0722.c,702 :: p1=&T[0];
MOVLW value_converter_T_L0+0
MOVWF value_converter_p1_L0+0
MOVLW hi_addr(value_converter_T_L0+0)
MOVWF value_converter_p1_L0+1


et le retour :

;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0722.c,711 :: return p1; // OK ;
MOVF value_converter_p1_L0+0, 0
MOVWF R0
MOVF value_converter_p1_L0+1, 0
MOVWF R1
;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0722.c,712 :: }
L_end_value_converter:
RETURN 0


déja , le Return 0
ne montre pas reellement que la fonction retourne un pointeur !
si ce n'est dans le contenu de R0 et R1 registre virtuels du compilateur
Aides toi, le ciel ou Fantastpic t'aideras

LCD 4x20 I2C Probleme avec Pointeur ,pas clair avec MikroC
satinas
Confirmé
Confirmé
Messages : 523
Enregistré en : novembre 2015

#2 Message par satinas » mer. 22 juil. 2020 19:42

Bonjour Paul, et bonjour à tous.

txt = value_converter(EA0);

Cet appel de fonction retourne un pointeur local p1 (avec p1 = T), donc txt va pointer sur le buffer T en sortie de fonction.
La suite du programme utilise donc T et pas TEXTE.
Le problème est que p1 et T ne sont plus valides car locaux, le compilateur réutilisera dès que possible les cases mémoire qu'ils occupaient.
Pourquoi tu ne remplis pas directement le buffer TEXTE dans la fonction.
Ou alors tu fais un strcpy(TEXTE, T) en fin de fonction.
Ou T disparaît et value_converter(EA0, TEXTE);

Le pointeur txt est-il vraiment utile ?

LCD 4x20 I2C Probleme avec Pointeur ,pas clair avec MikroC
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 1645
Enregistré en : juillet 2016
Localisation : Terre

#3 Message par Temps-x » jeu. 23 juil. 2020 01:08

Bonsoir paulfjujo, satinas, et tout le forum,

paulfjujo a écrit :Source du message Pour l'instant, en asm, l’écriture en dur à des adresses bien précises et CONNUES donnent ( :sifflotte: toujours) de bon resultats.

Merci ! et ouais, il y a que ça de vrai, car on sait ce qu'on fait...

paulfjujo a écrit :Source du message oops En C , on fait confiance au compilateur ...

:roll: Alors bonne chance.... :lol:

==> A+
:roll: Les requins, c'est comme le langage ASM, c'est le sommet de la chaîne alimentaire. :wink:

LCD 4x20 I2C Probleme avec Pointeur ,pas clair avec MikroC
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 1684
Âge : 69
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#4 Message par paulfjujo » jeu. 23 juil. 2020 11:04

bonjour à tous,


satinas a écrit :Le pointeur txt est-il vraiment utile ?

Code : Tout sélectionner


 TEXTE
=value_converter(EA0); // return a pointer
1016 318 Assigning to non-lvalue '' _18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c


D'une façon generale , j'utilise ce pointeur txt pour toute sortie sur ecran terminal ou LCD .
Et je preferre utiliser des pointeurs plutot que des indices de table
Ledit pointeur pouvant etre affecté à n'importe quelle table ..

je pense avoir trouvé le probleme, mais je n'ai pas d'outils
(In Circuit Debugger Tool) pour le mettre en evidence..

l'usage de pointeur est correct
mais il doit y avoir un probleme de STACK Overflow
en decomposant ma routine utilisée dans le main program
LCD_Puts(txt);

Code : Tout sélectionner


void LCD_puts
( char *s)
{
int i=0;
  while((*(s+i) != 0)&& (i<20))
  {
    LCD_putch(*(s+i));
    i++;
  }
}


par son contenu detaillé

Code : Tout sélectionner

 
 
   LCD_putcmd
(LCD_LINE4,1);
    // LCD_puts(txt);   //  <-------------   AUCUN affichage sur la 4em ligne avec appel de fonction
   // OK, si decomposition de la fonction
     i=0;
     while((*(txt+i) != 0)&& (i<20))
     {
        LCD_putch(*(txt+i));
        i++;
      }


je diminue ainsi les appels , donc reduit la position maxi dans la pile ..
Ce debordement de pile ne faisant pas de degat "visuel " tel que reset , difficile à cerner

Nota:
la version passage du pointeur comme argument ne posait pas de probleme , soit avec le pointeur txt, soit
avec directement le pointeur sur table TEXTE
ce qui m'interessait dans mon test , etait l'usage d'un pointeur retourné par une fonction.
retour de fonction pouvant d'ailleurs etre fait sur un unsigned int ou * pointeur
via R0,R1 registres 8 bits dans bank0 utilisé par le compilo

Code : Tout sélectionner


 _Value_converter
(EA0, TEXTE);
       UART1_Write_Text(TEXTE);
       CRLF1();
       LCD_putcmd(LCD_LINE1,1);
       LCD_puts(TEXTE);
      Delay_1sec();  



TempsX a écrit :et ouais, il y a que ça de vrai, car on sait ce qu'on fait...


exit j'attends de voir des exemples un peu plus complexe en asm , pour voir si c'est toujours aussi facile ...

voila ce que donne le resultat asm de compilation sur ce petit test

Code : Tout sélectionner



/ TEST
unsigned int  Test
(void)
{
char * px;
px=&TEXTE[0];
_asm nop ;
_asm nop;
return px ;
}



Code : Tout sélectionner

;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c,740 ::                 unsigned int  Test(void)
;
_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c,743 ::                 px=&TEXTE[0];
        MOVLW       _TEXTE+0
        MOVWF       R2 
        MOVLW       hi_addr
(_TEXTE+0)
        MOVWF       R3 
;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c,744 ::                 _asm nop ;
        NOP
;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c,745 ::                 _asm nop;
        NOP
;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c,746 ::                 return px ;
        MOVF        R2, 0 
        MOVWF       R0 
        MOVF        R3
, 0 
        MOVWF       R1 
;_18F46k22_Big_LCD_4x20_I2C1_HW_2020_0723.c,747 ::                 }
L_end_Test:
        RETURN      0
; end of _Test


avec le debugger mikroc
j'ai bien verifier que le pointeur retourné, pointe bien sur le debut de TEXTE

Code : Tout sélectionner

// TEST 
char *p1;
.....

  txt=&TEXTE[0];
  strConstRamCpy(TEXTE,"ABC");
  ICI:
  p1=Test();
  UART1_Write_Text(p1);
  CRLF1();
  
Aides toi, le ciel ou Fantastpic t'aideras

LCD 4x20 I2C Probleme avec Pointeur ,pas clair avec MikroC
satinas
Confirmé
Confirmé
Messages : 523
Enregistré en : novembre 2015

#5 Message par satinas » jeu. 23 juil. 2020 12:02

Une fonction C peut sans problème retourner l'adresse d'une variable globale ou d'un tableau global.
Dans ton premier post tu retournais l'adresse d'un tableau T local à la fonction, et continuais à le remplir par le biais de son adresse, car le C est très permissif. Cela pouvait tomber en marche au bon vouloir des compilations successives.

On peut quand même retourner l'adresse d'une variable locale, mais il faut la déclarer static.

LCD 4x20 I2C Probleme avec Pointeur ,pas clair avec MikroC
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 1684
Âge : 69
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#6 Message par paulfjujo » jeu. 23 juil. 2020 15:41

Merci ! Satinas,

c'est en effet la BONNE solution !

j'avais plutot l'habitude d'utiliser un passage de pointeur comme argument dans la fonction
ledit pointer étant global et par defaut static , ainsi que l'objet (table) pointée ... no problemo

All globals have static duration. ....


All functions, wherever defined, are objects with static duration.
......Other variables can be given static duration by using the explicit static or extern storage class specifiers.



confusion entre objet et variable , qui DOIT etre specifiée STATIC pour bloquer la reservation de l'espace en RAM
exclusivement à cet usage.

ça me rappelle les allocations memoires avec mem manager, heap reservation ...etc
qui existe aussi avec les PIC mais dont on ne se sert que tres rarement
(utilisé avec un LCD ILI9341)



les 2 versions :

Code : Tout sélectionner

// convert ADC value to a string with 3 decimal =>  0.000 to 5.000
char *  value_converter(unsigned int adc_value)
{
  static char T[8];  // <------  must be a STATIC variable
  long vout ;
  unsigned int value=0;
    vout= (long)adc_value * 5000 >>10;
    value = (unsigned int) vout;
       T[0] =  value/1000+48;   //Add 48 to get the ASCII character
       T[1]='.' ;
       T[2] = ( value/100)%10 +48;
       T[3] =  (value/10)%10 +48;
       T[4] = ( value %10) +48;
       T[5]=0;
     return T;
}



// .. OK if  pointer passed as parameter
void _Value_converter(unsigned int adc_value, char *T)
{
 
  long vout 
;
  unsigned int value;
    vout= (long)adc_value * 5000 >>10;
    value = (unsigned int) vout;
       T[0] =  value/1000+48;   //Add 48 to get the ASCII character
       T[1]='.' ;
       T[2] = ( value/100)%10+48;
       T[3] =  (value/10)%10 +48;
       T[4] = ( value %10) +48;
       T[5]=0;

}
Aides toi, le ciel ou Fantastpic t'aideras


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité