- 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 ---
Modérateur : Jérémy
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
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 =( (d & 0xF0) >>4 )| 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 = ( ( (d & 0xF0) >>4 ) | 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 = (d & 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 = ( (d & 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 !!
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
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.
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
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.
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 ( pas la biere Kwack) de l'administration publique...
...quoique trop d'abus de kwack peut generer aussi des couacs.. la boucle est bouclée.
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.
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
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.zipNon, 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 bitssatinas 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];
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++) { }
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
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 ....
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
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
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..
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,0 , //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(i = 0; i <64; i++)
{
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);
}
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
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 133 invités