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

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#1 Message par paulfjujo » ven. 31 mars 2023 20:52

bonsoir à tous ...


Encore une bizarrerie avec MPLAB XC8 2.36
test d'un afficheur LCd 2x16 avec une interface I2C1 via un PCF8754 @=0x20 (7 bits)

Affichage OK sauf que

Test cde I2C LCD PCF8754 @0x20 (7 bits) ..OK
test LCD avec problemo:

Code : Tout sélectionner


unint16_t i
,j,k;


void LCD_putch(unsigned char d)
{
  static unsigned char lcddata;
   // Put the Upper 4 bits data     on P0 ..P3
 
  lcddata 
=( (& 0xF0) >>)| LCD_RS;
  I2C_PCF8574_Write(Addr,lcddata | LCD_EN);
  __delay_us(5);      // __delay 2us for 16 MHz Internal Clock
  // Write Enable Pulse E: Hi -> Lo
  lcddata = (  ( (& 0xF0) >>) |  LCD_RS ) & (~LCD_EN) ;
  I2C_PCF8574_Write(Addr,lcddata);
  __delay_us(15);      // __delay 1us for 16 MHz Internal Clock
  // Put the Lower 4 bit data
  lcddata = (& 0x0F) | LCD_RS | LCD_EN;
  I2C_PCF8574_Write(Addr,lcddata);
  __delay_us(15);      // __delay 2us for 16 MHz Internal Clock
  // Write Enable Pulse E: Hi -> Lo
  lcddata = ( (& 0x0F) | LCD_RS ) & (~LCD_EN);
  I2C_PCF8574_Write(Addr,lcddata);
  __delay_us(15);      // __delay 1us for 16 MHz Internal Clock
}


void LCD_Write_CText(const char *txt)
{
  static int i1;
   i1=0;
   while ((*txt) && (i1<16))
   i1++;
   LCD_putch(*(txt++));
    __delay_ms(2);
 }


.... main programme ....
.. init hardware,uart,i2C ..

i=0;
while (1)
{
sprintf(CRam1,"I=% 5d 0X%04X ",i,i);
Print(CRam1);CRLF1();
i++;
SQA=1;
LCD_Write_Text_At(2,1,CRam1);
SQA=0;
__delay_ms(500);
__asm("btg LATB,5");
}

Affichage 1ere ligne "ABCDEFGHIJKLMNOP"
affichage sur 2em ligne du LCD (avec ^= espace)
I=^^125^0x007D^^

valeurs de I , uniquement Impaires comme si on faisait i=i+2 !
alors que sur le terminal YAT , on a bien une progression de 1


Test analyser SQA dans 4 sec
Init LCD I2C via PCF8754
123456789A Affichage sur LCD
Erase Line 1
Affichage LCD_Chr_AT(1,3,'0');
Erase Line 2
I= 0 0X0000
I= 1 0X0001
I= 2 0X0002
I= 3 0X0003
I= 4 0X0004
I= 5 0X0005
I= 6 0X0006
I= 7 0X0007
I= 8 0X0008
I= 9 0X0009



:!!: encore un mystere et boule de suif !!

_18F27K42_Chaudiere_LCD_OWS_2023.zip



idea ! une idée ?
nota : ma version 18F26K22 sous mikroC tourne OK sans probleme !


test uniquement de l'envoi I2C vers le PCF via SQA analyser
Test_envoi_data_IC2_PCF8754_20230331.jpg
Modifié en dernier par paulfjujo le lun. 3 avr. 2023 10:08, modifié 2 fois.
Aide toi, le ciel ou FantasPic t'aidera

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#2 Message par paulfjujo » ven. 31 mars 2023 20:55

oops doublon !
Aide toi, le ciel ou FantasPic t'aidera

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#3 Message par satinas » sam. 1 avr. 2023 06:24

Bonjour Paul, il manque le zip.

Pourquoi déclarer en static les variables lcddata et i1 ?

Tu peux raccourcir les lignes lcddata, on passe un octet d à la fonction.
lcddata = (d >> 4) | LCD_RS | LCD_EN;
lcddata &= ~LCD_EN ;
lcddata = (d & 0x0F) | LCD_RS | LCD_EN;
lcddata &= ~LCD_EN ;

Il manque les accolades du while dans LCD_Write_CText(), dans l'état cette fonction n'affiche qu'un seul caractère.

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#4 Message par paulfjujo » sam. 1 avr. 2023 09:43

bonjour Satinas et à tous ,


satinas a écrit :Bonjour Paul, il manque le zip.


il est dans e doublon ...

satinas a écrit :Pourquoi déclarer en static les variables lcddata et i1 ?


juste un test pour voir ...si ça resolvait mon probleme ..

satinas a écrit :Tu peux raccourcir les lignes lcddata, on passe un octet d à la fonction.
lcddata = (d >> 4) | LCD_RS | LCD_EN;
lcddata &= ~LCD_EN ;
lcddata = (d & 0x0F) | LCD_RS | LCD_EN;
lcddata &= ~LCD_EN ;


Non, car il faut que je passe en 2 fois,
il faut envoyer un front descendant de ENable ,apres la mise ne place des quartets de data 4 bits


satinas a écrit :Il manque les accolades du while dans LCD_Write_CText(), dans l'état cette fonction n'affiche qu'un seul caractère.


effectivement, c'est un "résidu" de test.

idea ! J'ai trouvé là ou ça coince :

j'utilisait un Tampon intermediaire ... inutile d'ailleurs !

Code : Tout sélectionner


void LCD_Write_Text_At
(unsigned char Ligne,unsigned char col, char * t1)
{
 
    strcpy
(Tampon,t1);
    if (strlen(Tampon)>NbCarPL) *(Tampon+16)=0;
   if(col>NbCarPL) col=NbCarPL-1;
  if (Ligne==1) LCD_putcmd(0x80+col-1,0);
  if (Ligne==2) LCD_putcmd(0xC0+col-1,0);
  LCD_puts(Tampon);
}



modifié ,simplifié :

Code : Tout sélectionner


void LCD_Write_Text_At
(unsigned char Ligne,unsigned char col, char * t1)
{
 
  if 
(strlen(t1)>NbCarPL) *(t1+16)=0;
  if(col>=NbCarPL) col=NbCarPL-1;
  if (Ligne==1) LCD_putcmd(0x80+col-1,1);
  if (Ligne==2) LCD_putcmd(0xC0+col-1,1);
  LCD_puts(t1);
}


j'ai maintenant l'affichage qui est conforme, progression de +1 (idem que sur terminal YAT)
:?: :?: C'est quand même tres curieux ce genre de probleme ! (Effets de bords, Bordeline ...)

A l'époque du tout numérique , ça craint un maximum ..si un bug latent traine dans un code
.. et ce code qui va piloter ta voiture ! j'espere qu'un mode MANUEL est prévu.
Jusqu' à quel point un code est verifiable , testable ... si en plus il y a des errata (silicium) dans le MCU utilisé!
ou le compilateur .. ou des neurones grillés ..

et ça explique aussi , en partie, les Couaks ( :sifflotte: pas la biere Kwack) de l'administration publique...
kwackt.gif
...quoique trop d'abus de kwack peut generer aussi des couacs.. la boucle est bouclée.
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#5 Message par satinas » sam. 1 avr. 2023 10:03

il est dans le doublon ...

Tu nous fait un 1er avril, je vois rien :-)

Non, car il faut que je passe en 2 fois,
il faut envoyer un front descendant de ENable ,apres la mise ne place des quartets de data 4 bits

Mes lignes lcddata font exactement la même chose que les tiennes, sauf erreur. Je n'ai bien sûr pas mis les autres lignes envoi et tempo.
Le (d & 0xF0) est inutile car derrière (d >> 4) remplace les 4 bits b3 à b0.

j'utilisais un Tampon intermediaire ... inutile d'ailleurs !

*(Tampon+16) ne pose pas de problème si Tampon est un tableau de char. Si Tampon est un tableau de int, *(Tampon+16) pointe sur le 17ème int du tableau, donc offset de 32 octets par rapport au début du tableau. Où alors *( ((char*)Tampon) + 16) = 0;
Un tableau ou un pointeur connaît la taille de ce sur quoi il pointe, si tu lui ajoutes un offset, il le multiplie par cette taille pour avoir l'adresse finale.

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#6 Message par paulfjujo » sam. 1 avr. 2023 16:07

satinas a écrit :
il est dans le doublon
Tu nous fait un 1er avril, je vois rien :-)...

... dans le doublon dis-je
viewtopic.php?f=10&t=1297
_18F27K42_Chaudiere_LCD_OWS_2023.zip

Non, car il faut que je passe en 2 fois,
il faut envoyer un front descendant de ENable ,apres la mise ne place des quartets de data 4 bits


satinas a écrit :Mes lignes lcddata font exactement la même chose que les tiennes,
sauf erreur. Je n'ai bien sûr pas mis les autres lignes envoi et tempo.
Le (d & 0xF0) est inutile car derrière (d >> 4) remplace les 4 bits b3 à b0.


sauf que, dans mon cas, au niveau hardware , c'est mon PORT PCF8754 P0..P3 qui pilote le LCD en D4..D7
il faut donc que je les recentre sur ceux ci via le decalage.


j'utilisais un Tampon intermediaire ... inutile d'ailleurs !

*(Tampon+16) ne pose pas de problème si Tampon est un tableau de char. Si Tampon est un tableau de int, *(Tampon+16) pointe sur le 17ème int du tableau, donc offset de 32 octets par rapport au début du tableau. Où alors *( ((char*)Tampon) + 16) = 0;
Un tableau ou un pointeur connaît la taille de ce sur quoi il pointe, si tu lui ajoutes un offset, il le multiplie par cette taille pour avoir l'adresse finale.


tampon declaré:
uint8_t Tampon[32];

PCF8754_interface_LCD1602_schem.jpg
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#7 Message par satinas » sam. 1 avr. 2023 16:28

La variable NbCarPL n'est jamais renseignée ?
Tampon[16] serait plus académique, mais *(Tampon+16) doit passer. Sans tester impossible d'en dire plus. Le debugger est fait pour cela.

Ta fonction strConstRamCpy() ajoute 2 terminateurs de fin de chaîne destination, une fois dans la boucle et une deuxième fois après la boucle.

Code : Tout sélectionner

void strConstRamCpy(uint8_t  *dest, const  uint8_t *source)
{
  while (*source) *dest++ = *source++;
  *dest = 0;
}

2 exemples de copie chaîne en une seule instruction :)

Code : Tout sélectionner

  do *dest++ = *source; while (*source++);
  while (*dest++ = *source++) { }

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#8 Message par paulfjujo » sam. 1 avr. 2023 20:15

satinas a écrit :La variable NbCarPL n'est jamais renseignée ?
Tampon[16] serait plus académique, mais *(Tampon+16) doit passer. Sans tester impossible d'en dire plus. Le debugger est fait pour cela.

Ta fonction strConstRamCpy() ajoute 2 terminateurs de fin de chaîne destination, une fois dans la boucle et une deuxième fois après la boucle.

Code : Tout sélectionner

void strConstRamCpy(uint8_t  *dest, const  uint8_t *source)
{
  while (*source) *dest++ = *source++;
  *dest = 0;
}

2 exemples de copie chaîne en une seule instruction :)

Code : Tout sélectionner

  do *dest++ = *source; while (*source++);
  while (*dest++ = *source++) { }



NbCarPL est une constante initialisée à 16 ( pour un LCD 2x16)

Tampon ne sert pas qu'au LCD ...

effectivement ceinture + bretelle
ceinture est suffisante ....
Aide toi, le ciel ou FantasPic t'aidera

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#9 Message par paulfjujo » lun. 3 avr. 2023 10:34

Bonjour à tous,

j'ai réouvert ce post suite à cette remarque...

I2C1 Sous MPLABX

void I2C1_Initialize()
La frequence de SCL clock I2C est issue de
//CLK MFINTOSC;
I2C1CLK = 0x03;
hors MFINTOSC est à 500KHz
une mesure sur le signal RC3 donne SCL = 100KHz

:!!: je ne vois pas comment on arrive à cette valeur ...

L'init de mon LCD a des ratées ...
J'ai soupsonné la fréquence de SCL Clock
vu que le PCF8754 est donné pour SCL max 100KHz
j'ai essayé de réduire la vitesse de l'I2C
en utilisant la sortie Timer2 comme source

Code : Tout sélectionner


void Init_Timer2
()
{
 
  T2CON    
= 0x00;
  T2CONbits.CKPS2=0;// div 1/1 
  T2CONbits.CKPS1=0;
  T2CONbits.CKPS0=0;
  T2CONbits.OUTPS=1;  // div 1/2
  T2PR=190;  // 0.0625 * 1 * 2 * 190 =23.75 µS  =>  42Khz
  T2TMR=0;
  T2CLK=0x02; //1= FOSC/4    2=FOSC     5=500Khz   
 // REGISTER 22-2: TxRST: TIMER2 EXTERNAL RESET SIGNAL SELECTION REGISTER p337
  T2RST=0x04;  // CCP1OUT
  PIE4bits.TMR2IE=0;
  PIR4bits.TMR2IF=0;
  T2CONbits.T2ON=1;
}
 


:!!: j'ai un doute sur le contenu du registre T2RST !

modif code init I2C


Mon analyser logique me montre une fréquence de 33KHz au lieu de 42Khz
18,020µS ON ......11.760 µs Off
erreur quelque part ?

nota : à SCLK= 100Khz .......j'ai 6.16µS ON ....3.82µS OFF => 9,98µS -> 100,2Khz

Code : Tout sélectionner


void Init_I2C 
(void)
{
   
  
// I2C1CLK    = 0x03;      // I2C1 Clock Selection Register, MFINTOSC 500kHz ??  mesuré 100kHz ??  doc p. 581
      I2C1CLK    = 0x06;    ///0110     TMR2 post scaled output    42Khz theorique
                                                      // SQA mesure  18.00+11.76=29.76µS -> 33.6Khz ?? why ?
    I2C1CON0   = 0x04;      // I2C1 Control Register 0, Master mode, 7-bit Address  // doc p.577
    I2C1CON1   = 0x80;      // I2C1 Control Register 1, Acknowledge value transmitted after received data 
                            //(when I2CCNT=0) : 1 = NACK     (Not ACKnowledge)  // doc p.579
    I2C1CON2   = 0x00;   
   
//  Control Register 2, envoi Start non auto, SDAHT 300ns hold time, BFRET 8 i2c clock pulses  // doc p.580
    I2C1CNT = 0;
    I2C1CON2bits.ABD=0; //  ADB=0; // Transmitted Address data is loaded from the I2CxADB0/1 registers.
     // I2C1ADB1   = 0x3C;      //0x3C adresse bus I2C mini oled SSD1306
    I2C1ADB1   = 0x20 ;   //LCD_ADDR;   // LCD 2x16 avec PCF8754
    I2C1PIRbits.PCIF = 0;  // clear STOP bit flag
    I2C1CON0bits.EN=1;    
}
 


mon probleme n'est pas sur le couple PCF + LCD, vu qu'en MikroC , ça tourne OK, no problemo

idea ! Probleme localisé autour de l'usage des caracteres CGRAM
et table de stockage des 3x64 bytes.. (3 jeux de carateres speciaux)
qui s'affichent correctement sur mon LCD !!!

Le probleme d'init LCD apparait 1 fois sur 10 redémarragesapplication
par BP reset ... c'est pas flagrant..

:furieux:
nota: MPLABX ne se preoccupe pas de la taille des tables definies en const ( flash) !
aucune erreur à la compilation quelque soit la taille definie ou pas ....
alors que MikroC sait gerer la taille des tables .. en comptant le nb de valeurs definies dedans !

ma declaration caracteres speciaux :

Code : Tout sélectionner


const unsigned char LCD_Custom_Chars
[3*64] =
{
//---------- set #1 ------------------
0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00,  //char #1   Degrée
0x06,0x09,0x08,0x1E,0x1E,0x08,0x09,0x06,  //char #2   euro
0x04,0x0A,0x11,0x11,0x0A,0x0A,0x11,0x00,  // char #3  Ohm
4,14,14,14,31,0,4,0,                      // char #4   bell
28,20,27,18,19,18,18,,                  //char #5 initiales PF
0x01,0x03,0x07,0x0F,0x07,0x03,0x01,0x00,  //char #6  A gauche
0x00,0x11,0x0A,0x04,0x06,0x11,0x00,0x00,  //char #7 cancel
0x00,0x01,0x03,0x16,0x1C,0x10,0x00,0x00,  //char #8  Checked

//-----Barre verticales   set #2   0 à 6 colonnes , mais seulement 5 maxi en 5x8 cars  -------
0b10000000,0b10000000,0b10000000,0b10000000,0b10000000,0b10000000,0b10000000,0b10000000,
0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,
0b11100000,0b11100000,0b11100000,0b11100000,0b11100000,0b11100000,0b11100000,0b11100000,
0b11110000,0b11110000,0b11110000,0b11110000,0b11110000,0b11110000,0b11110000,0b11110000,
0b11111000,0b11111000,0b11111000,0b11111000,0b11111000,0b11111000,0b11111000,0b11111000,
0b11111100,0b11111100,0b11111100,0b11111100,0b11111100,0b11111100,0b11111100,0b11111100,
0b11111110,0b11111110,0b11111110,0b11111110,0b11111110,0b11111110,0b11111110,0b11111110,
0b11111111,0b11111111,0b11111111,0b11111111,0b11111111,0b11111111,0b11111111,0b11111111,
//------- Set #3  ----------------------

0,0,0,0,27,27,27,27,
27,27,27,27,0,0,0,0,
3,3,3,3,24,24,24,24,
24,24,24,24,3,3,3,3,
0,0,0,31,31,31,31,31,
0,0,31,31,31,31,31,31,
0,31,31,31,31,31,31,31,
31,31,31,31,31,31,31,31
};
const char *Special_Name[24*7]=
{
"DEGREE","EURO  ","OHM   ","PF    ","Droite","Gauche","CANCEL","Check.", // pour caracteres Speciaux
 "Zero  ","un    ","deux  ","trois ","quatre","cinq  ","six   ","Sept  ",// pour Barre Graphe Horizontale
 "Zero  ","un    ","deux  ","trois ","quatre","cinq  ","six   ","Sept  "};// pour barre Graphe Vertical



chargement code speciaux

Code : Tout sélectionner



void LCD_Load_Custom_Chars
(unsigned char Set)
{
 
unsigned int  i;
 
unsigned int  k;
 
// Set address counter pointing to CGRAM address 0.
 
LCD_Cmd(0x40);
 
// Load custom lcd character data into CGRAM.
 // maximum of 8 custom characters.
   
k=0;
  for(
0<64i++)
  {
  if ( (
i>0) && (i%8==0))
     {
     
CPrint(Special_Name[k+ (Set<<3)]);
     
k++;
      
CRLF1();
    }
    
LCD_Data(LCD_Custom_Chars[i+ (Set<<6)]);
    
Decompile_byte(  LCD_Custom_Chars[i+ (Set<<6)]);
    
CRLF1();
  }
 
CPrint(Special_Name[k+ (Set<<3)]); 
 
// Set address counter pointing back to the DDRAM.
 
LCD_Cmd(0x80);
  
__delay_ms(150);
Modifié en dernier par paulfjujo le lun. 3 avr. 2023 11:35, modifié 1 fois.
Aide toi, le ciel ou FantasPic t'aidera

LCD2x16 I2C via PCF8754 MPLAB XC8 bug ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#10 Message par satinas » lun. 3 avr. 2023 10:42

Bonjour,
un peu de lecture le temps que je finisse de lire ton post :)
viewtopic.php?p=19363#p19363

D'après ce que je comprends :
Le registre T2HLT définit le mode de pilotage du timer, démarrage/reset/stop sont déclenchables sur évènement extérieur, soit pin T2INPPS, soit signal provenant d'un autre périphérique (CCP_out, CLC_out, UART_rx), on sélectionne cela avec le registre T2RST.
Par défaut T2HLT est à 0, mode 0, le timer tourne de manière conventionnelle (Table 22-1), Free Running Period et Software gate. Start et stop avec le bit ON, et reset sur overflow. T2RST est à 0 par défaut, donc pilotage par input T2INPPS, mais inhibé car mode 0.

Le timer tourne avec FOSC donc Ftimer = 64000000/2/190 -> 168421Hz
Pour l'i2c c'est Fscl = 168421/5 = 33,68kHz


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 32 invités