Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] PIC 16F887 > LCD 2 x 16 > 4 datas bits > Can not print on LCD a char or a string

Status
Not open for further replies.

Eric_O

Advanced Member level 4
Joined
May 31, 2020
Messages
104
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Activity points
996
Bonsoir,

Here in the attached file my code. I do not understand why Lcd_Out routine of Mikroe runs only. When I tried to run my own routines (2 versions), lines 161 to 166 ... here after, I can't display the string "Bonjour !". In the code I insert "//" in front of these 6 routines, in order to test each, one after one.

LCD_Write_String("Bonjour !");
LCD_Write_String_v2("Bonjour !");
LCD_String_Position(1, 1, "Bonjour !");
LCD_String_Position_v2(1, 1, "Bonjour !");
LCD_String_Position(1, 1, *pointeur_de_char);
LCD_String_Position_v2(1, 1, *pointeur_de_char);

Do anyone have an idea why they do not run ?

Merci beaucoup !

Eric
 

Attachments

  • PIC 16F887 - LCD - MikroC - My own outines failed.txt
    6.7 KB · Views: 110

no idea.
however, it will help if you include:
the part number of the display,
the connections you make between the processor and the display?
power and ground connections
 

Hello Eric,


Do anyone have an idea why they do not run ?

remark :
Code:
void LCD_Write_Data(char mot)
l'usage de mot pour un byte n'est pas heureuse, ni recommandée
use instead "mot" -> octet


did you test before with only one charactere to display ?
i think , LCD init is wrong .. because Init must strat in 8 bit configuration before to change to 4 bits ...

0X30 commande are missing !

Code:
   CPrint1(" Test avec init LCD en ASM , SANS LA Lib MikroC\r\n");
   //  Init_LCD_in_ASM() ;

_asm{
BCF         LCD_EN_Direction, BitPos(LCD_EN_Direction+0)
BCF         LCD_RS_Direction, BitPos(LCD_RS_Direction+0)
BCF         LCD_D4_Direction, BitPos(LCD_D4_Direction+0)
BCF         LCD_D5_Direction, BitPos(LCD_D5_Direction+0)
BCF         LCD_D6_Direction, BitPos(LCD_D6_Direction+0)
BCF         LCD_D7_Direction, BitPos(LCD_D7_Direction+0)
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_RS, BitPos(LCD_RS+0)
BCF         LCD_D7, BitPos(LCD_D7+0)
BCF         LCD_D6, BitPos(LCD_D6+0)
BCF         LCD_D5, BitPos(LCD_D5+0)
BCF         LCD_D4, BitPos(LCD_D4+0)
RCALL       _Delay_5500us
RCALL       _Delay_5500us
RCALL       _Delay_5500us
BSF         LCD_D5, BitPos(LCD_D5+0)
BSF         LCD_D4, BitPos(LCD_D4+0)    // 0x30
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x30
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x30
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D4, BitPos(LCD_D4+0)   // 0x20
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x20
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_D5, BitPos(LCD_D5+0)   // 0x00
BSF         LCD_D7, BitPos(LCD_D7+0)   // 0x80
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D7, BitPos(LCD_D7+0)  //0x00
BSF         LCD_D4, BitPos(LCD_D4+0)  //0x10
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0)  // 0x00
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BSF         LCD_D4, BitPos(LCD_D4+0) // 0x10
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0) //0x00
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BSF         LCD_D7, BitPos(LCD_D7+0)
BSF         LCD_D6, BitPos(LCD_D6+0)
BSF         LCD_D5, BitPos(LCD_D5+0)
BSF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0) //0xF0
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
MOVLB       0
BSF         0x7D,1; //__Lib_Lcd_cmd_status, BitPos(__Lib_Lcd_cmd_status+0), 1
RETURN      0

Delay_5500us:
MOVLW       115
MOVWF       R12, 0
MOVLW       71
MOVWF       R13, 0
L_Delay_5500:
DECFSZ      R13, 1, 0
BRA         L_Delay_5500
DECFSZ      R12, 1, 0
BRA         L_Delay_5500
NOP
NOP
RETURN  0

Delay_1us:
MOVLW       5
MOVWF       R13, 0
L_Delay_1us:
DECFSZ      R13, 1, 0
BRA         L_Delay_1us
RETURN      0

}
 
Last edited:

I think the problem is in your LCD_Write_Cmd() and LCD_Write_Data() commands.

The lines like "PORTB = mot >>4;" and "PORTB = mot & 0x0F;" are to isolate the upper then lower 4-bits of the data so it can be sent to the LCD in two write operations but you write 8-bits to PORTB each time. RB4 and RB5 are also being written and these are the control signals to the LCD.

Brian.
 

no idea.
however, it will help if you include:
the part number of the display,
the connections you make between the processor and the display?
power and ground connections
At thé begining of my code there is « // LCD module connections : ». Have à look.
LCD is the most popular : Hitachi HD4480.
 

Try this change and apply it also to the LCD_Write_Data() code:
Code:
void LCD_Write_Cmd(unsigned char mot)                         // Version 3 : OK.
{
LCD_RS = 0;
Delay_us(5);
LCD_D4 = ((mot & 0x10) == 0x10)?1:0;                         // Send upper nibble.
LCD_D5 = ((mot & 0x20) == 0x20)?1:0;
LCD_D6 = ((mot & 0x40) == 0x40)?1:0;
LCD_D7 = ((mot & 0x80) == 0x80)?1:0;
//PORTB = mot >> 4;                                         
LCD_E_Pulse();
LCD_D4 = ((mot & 0x01) == 0x01)?1:0;                         // Send upper nibble.
LCD_D5 = ((mot & 0x02) == 0x02)?1:0;
LCD_D6 = ((mot & 0x04) == 0x04)?1:0;
LCD_D7 = ((mot & 0x08) == 0x08)?1:0;
//PORTB = mot & 0x0F;                                          // Send lower nibble.
LCD_E_Pulse();
}
I do not have a copy of MikroC but the above should work with it. The idea is NOT to write to the whole of PORTB but to set/reset individual bits before pulsing the 'E' line. It also allows the pins to be re-allocated freely, even across different ports as long as you change the definitions appropriately.

Brian.
 
  • Like
Reactions: eagle1109

    eagle1109

    Points: 2
    Helpful Answer Positive Rating

    Eric_O

    Points: 2
    Helpful Answer Positive Rating
Hi,
At thé begining of my code there is « // LCD module connections : ». Have à look.
If you want us to help you we need something to validate with.
A single source always is correct.
Usually we like to see code and schematic, so we can check if both match.

In post#1 you refer to line numbers, but I don't see line numbers in your sources.

Undocumented code never is a good idea, even not if it is just for yourself.
But posting it in a forum surely reduces feedback.

I've written many ASM programs. I've spent some time to find out what you want to achieve...but it's more difficult on a foreign code than on one owns code.

Klaus
 

@KlausST,

The code that Eric_O posted is one of the better efforts I have seen so far this year.

After creating a microC project for the PIC16F887 and including support from the microC LCD library for a 16x2 LCD module the code compiles without any diagnostic messages (no errors or warnings).

That said there are some errors in Eric_O's implementation.

Some have already been mentioned, but another is much more subtle.

The sequence of commands to get the LCD module in to 4-bit parallel mode will only work one time immediately after the module has been powered on.
 

Hi,

A motor is only one part of a car. But it needs more than a perfectly serviced motor to safely drive from A to B.
Wheels, fuel, a driver, a road, a map .... a own's mistake, another person's mistake, snow, jam, roadworks, a ferry...

Klaus
 

Hello Eric,

remark :
Code:
void LCD_Write_Data(char mot)
l'usage de mot pour un byte n'est pas heureuse, ni recommandée
use instead "mot" -> octet


did you test before with only one charactere to display ?
i think , LCD init is wrong .. because Init must strat in 8 bit configuration before to change to 4 bits ...

0X30 commande are missing !

Code:
   CPrint1(" Test avec init LCD en ASM , SANS LA Lib MikroC\r\n");
   //  Init_LCD_in_ASM() ;

_asm{
BCF         LCD_EN_Direction, BitPos(LCD_EN_Direction+0)
BCF         LCD_RS_Direction, BitPos(LCD_RS_Direction+0)
BCF         LCD_D4_Direction, BitPos(LCD_D4_Direction+0)
BCF         LCD_D5_Direction, BitPos(LCD_D5_Direction+0)
BCF         LCD_D6_Direction, BitPos(LCD_D6_Direction+0)
BCF         LCD_D7_Direction, BitPos(LCD_D7_Direction+0)
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_RS, BitPos(LCD_RS+0)
BCF         LCD_D7, BitPos(LCD_D7+0)
BCF         LCD_D6, BitPos(LCD_D6+0)
BCF         LCD_D5, BitPos(LCD_D5+0)
BCF         LCD_D4, BitPos(LCD_D4+0)
RCALL       _Delay_5500us
RCALL       _Delay_5500us
RCALL       _Delay_5500us
BSF         LCD_D5, BitPos(LCD_D5+0)
BSF         LCD_D4, BitPos(LCD_D4+0)    // 0x30
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x30
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x30
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D4, BitPos(LCD_D4+0)   // 0x20
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x20
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_D5, BitPos(LCD_D5+0)   // 0x00
BSF         LCD_D7, BitPos(LCD_D7+0)   // 0x80
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D7, BitPos(LCD_D7+0)  //0x00
BSF         LCD_D4, BitPos(LCD_D4+0)  //0x10
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0)  // 0x00
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BSF         LCD_D4, BitPos(LCD_D4+0) // 0x10
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0) //0x00
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BSF         LCD_D7, BitPos(LCD_D7+0)
BSF         LCD_D6, BitPos(LCD_D6+0)
BSF         LCD_D5, BitPos(LCD_D5+0)
BSF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0) //0xF0
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
MOVLB       0
BSF         0x7D,1; //__Lib_Lcd_cmd_status, BitPos(__Lib_Lcd_cmd_status+0), 1
RETURN      0

Delay_5500us:
MOVLW       115
MOVWF       R12, 0
MOVLW       71
MOVWF       R13, 0
L_Delay_5500:
DECFSZ      R13, 1, 0
BRA         L_Delay_5500
DECFSZ      R12, 1, 0
BRA         L_Delay_5500
NOP
NOP
RETURN  0

Delay_1us:
MOVLW       5
MOVWF       R13, 0
L_Delay_1us:
DECFSZ      R13, 1, 0
BRA         L_Delay_1us
RETURN      0

}
Thanks Paul !
Finally I found time to study all of your advices.
Hello Eric,




remark :
Code:
void LCD_Write_Data(char mot)
l'usage de mot pour un byte n'est pas heureuse, ni recommandée
use instead "mot" -> octet


did you test before with only one charactere to display ?
i think , LCD init is wrong .. because Init must strat in 8 bit configuration before to change to 4 bits ...

0X30 commande are missing !

Code:
   CPrint1(" Test avec init LCD en ASM , SANS LA Lib MikroC\r\n");
   //  Init_LCD_in_ASM() ;

_asm{
BCF         LCD_EN_Direction, BitPos(LCD_EN_Direction+0)
BCF         LCD_RS_Direction, BitPos(LCD_RS_Direction+0)
BCF         LCD_D4_Direction, BitPos(LCD_D4_Direction+0)
BCF         LCD_D5_Direction, BitPos(LCD_D5_Direction+0)
BCF         LCD_D6_Direction, BitPos(LCD_D6_Direction+0)
BCF         LCD_D7_Direction, BitPos(LCD_D7_Direction+0)
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_RS, BitPos(LCD_RS+0)
BCF         LCD_D7, BitPos(LCD_D7+0)
BCF         LCD_D6, BitPos(LCD_D6+0)
BCF         LCD_D5, BitPos(LCD_D5+0)
BCF         LCD_D4, BitPos(LCD_D4+0)
RCALL       _Delay_5500us
RCALL       _Delay_5500us
RCALL       _Delay_5500us
BSF         LCD_D5, BitPos(LCD_D5+0)
BSF         LCD_D4, BitPos(LCD_D4+0)    // 0x30
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x30
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x30
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D4, BitPos(LCD_D4+0)   // 0x20
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)   // 0x20
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_D5, BitPos(LCD_D5+0)   // 0x00
BSF         LCD_D7, BitPos(LCD_D7+0)   // 0x80
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D7, BitPos(LCD_D7+0)  //0x00
BSF         LCD_D4, BitPos(LCD_D4+0)  //0x10
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BCF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0)  // 0x00
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BSF         LCD_D4, BitPos(LCD_D4+0) // 0x10
BSF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
BCF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0) //0x00
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
BSF         LCD_D7, BitPos(LCD_D7+0)
BSF         LCD_D6, BitPos(LCD_D6+0)
BSF         LCD_D5, BitPos(LCD_D5+0)
BSF         LCD_D4, BitPos(LCD_D4+0)
BSF         LCD_EN, BitPos(LCD_EN+0) //0xF0
RCALL       _Delay_1us
BCF         LCD_EN, BitPos(LCD_EN+0)
RCALL       _Delay_5500us
MOVLB       0
BSF         0x7D,1; //__Lib_Lcd_cmd_status, BitPos(__Lib_Lcd_cmd_status+0), 1
RETURN      0

Delay_5500us:
MOVLW       115
MOVWF       R12, 0
MOVLW       71
MOVWF       R13, 0
L_Delay_5500:
DECFSZ      R13, 1, 0
BRA         L_Delay_5500
DECFSZ      R12, 1, 0
BRA         L_Delay_5500
NOP
NOP
RETURN  0

Delay_1us:
MOVLW       5
MOVWF       R13, 0
L_Delay_1us:
DECFSZ      R13, 1, 0
BRA         L_Delay_1us
RETURN      0

}
Thank you Paul,
Finally, when adding 0X30, it works better !
Your assembler code looks interresting. Generaly assembler is not my favorite language. Will have a look in detail later.
--- Updated ---

Try this change and apply it also to the LCD_Write_Data() code:
Code:
void LCD_Write_Cmd(unsigned char mot)                         // Version 3 : OK.
{
LCD_RS = 0;
Delay_us(5);
LCD_D4 = ((mot & 0x10) == 0x10)?1:0;                         // Send upper nibble.
LCD_D5 = ((mot & 0x20) == 0x20)?1:0;
LCD_D6 = ((mot & 0x40) == 0x40)?1:0;
LCD_D7 = ((mot & 0x80) == 0x80)?1:0;
//PORTB = mot >> 4;                                     
LCD_E_Pulse();
LCD_D4 = ((mot & 0x01) == 0x01)?1:0;                         // Send upper nibble.
LCD_D5 = ((mot & 0x02) == 0x02)?1:0;
LCD_D6 = ((mot & 0x04) == 0x04)?1:0;
LCD_D7 = ((mot & 0x08) == 0x08)?1:0;
//PORTB = mot & 0x0F;                                          // Send lower nibble.
LCD_E_Pulse();
}
I do not have a copy of MikroC but the above should work with it. The idea is NOT to write to the whole of PORTB but to set/reset individual bits before pulsing the 'E' line. It also allows the pins to be re-allocated freely, even across different ports as long as you change the definitions appropriately.

Brian.

Brian,

Sorry for my late repply. I had no time till yesterday to study your answer. Yes, it's completly true, I made a huge understanding mistake while writing my routines LCD_Write_Cmd(...) and LCD_Write_Data(...). Thank you for highlight it.
Before I needed to decode lines with ? and : ... Very interresting instruction. We save lines, probably bytes and time execution.
I copied / paste your code for both routines.

Each of followings routines in my code works now properly but with a Delay of 2 mS just before.

LCD_Write_String("Bonjour !");
LCD_Write_String_v2("Bonjour !");
LCD_String_Position(1, 1, "Bonjour !");
LCD_String_Position_v2(1, 1, "Bonjour !");

But these followings routines still not run :

LCD_String_Position(1, 1, *pointeur_de_char);
LCD_String_Position_v2(1, 1, *pointeur_de_char);

I guess I have some errors with my pointers ... because not easy to understand ... Declarations are maybe wrong ...
Will try to run them step by step with debbugger.

Any idea, advice or code are velcomed.

Merci beaucoup !

Eric
 
Last edited by a moderator:

hello Eric,

*pointer => contenu (char) pointé par le pointeur
pointer => seul = adresse zone pointée

Code:
  unsigned char *pointeur_de_char;         // Déclaration d'un pointeur (*) de char "pointeur_de_char".
  char texte[17]; // pour LCD de 16 chars/ligne
  pointeur_de_char = &texte[0];

// --- Copie le texte depuis FLASH ROM vers RAM

void strConstRamCpy(unsigned char *dest, const code char *source)
{
  while (*source)*dest++ = *source++ ;
  *dest = 0 ;    // terminateur
}

void LCD_Write_CString(const char *msg)                     
{
while ((*msg) != 0)                                          // Send each char of string till the 0.
    {
     LCD_Write_Data(*msg);
     *msg++;  // pointeur msg modifié !
    }
}


void LCD_Write_String_v2(char *msg)            
{
// variante avec pointeur msg non modifié
int k;
k=0;
while( *(msg)>0)
{
    LCD_Write_Data(*(msg+k));   // data pointée par msg+k
    k++;
    if (k>15) break;
   }
}

void LCD_CString_Position(char row, char col, const char *msg)
{
char location = 0;
  switch (row):
    {
    case 1:
     location = (0x80) | ((col) & 0x0F);     // Print message on 1st row and desired location.
     break;
    case 2:
       location = (0xC0) | ((col) & 0x0F);   // Print message on 2nd row and desired location.
       break;
    default:
    break;
    }  
    LCD_Write_Cmd(location);
    LCD_Write_String(msg);  //  <-- au lieu de *msg
}


void LCD_String_Position_v2(char row, char col, char *msg)
{
if (row == 1)
    {
     LCD_Write_Cmd((col & 0x0F)|0x80);   // Print message on 1st row and desired location.
    }
else if (row == 2)
    {
     LCD_Write_Cmd((col & 0x0F)|0xC0);      // Print message on 2nd row and desired location.
    }
LCD_Write_String_v2(msg);
}

... main  program...

  Lcd_Init_v3();                                           // Initialize LCD.
  while(1)                                                  // Endless loop.
{
  pointeur_de_char=&texte[0];  // <- au cas ou le pointeur serais altéré
  portc.b2 = 1;
  Lcd_Out(1, 1, "Bonjour ! ");
  strConstRamCpy(pointeur_de_char,"Bonjour !");
  Lcd_Out(1, 1, pointeur_de_char);                        
  LCD_CString_Position(1, 1,"Bonjour !");
  pointeur_de_char=&texte[0];  // <- au cas ou le pointeur serais altéré
  strConstRamCpy(pointeur_de_char,"Bonjour !");
  LCD_String_Position_v2(1, 1, pointeur_de_char);
  Delay_ms(1000);
}
 
Last edited:

    Eric_O

    Points: 2
    Helpful Answer Positive Rating
hello Eric,

*pointer => contenu (char) pointé par le pointeur
pointer => seul = adresse zone pointée

Code:
  unsigned char *pointeur_de_char;         // Déclaration d'un pointeur (*) de char "pointeur_de_char".
  char texte[17]; // pour LCD de 16 chars/ligne
  pointeur_de_char = &texte[0];

// --- Copie le texte depuis FLASH ROM vers RAM

void strConstRamCpy(unsigned char *dest, const code char *source)
{
  while (*source)*dest++ = *source++ ;
  *dest = 0 ;    // terminateur
}

void LCD_Write_CString(const char *msg)                
{
while ((*msg) != 0)                                          // Send each char of string till the 0.
    {
     LCD_Write_Data(*msg);
     *msg++;  // pointeur msg modifié !
    }
}


void LCD_Write_String_v2(char *msg)       
{
// variante avec pointeur msg non modifié
int k;
k=0;
while( *(msg)>0)
{
    LCD_Write_Data(*(msg+k));   // data pointée par msg+k
    k++;
    if (k>15) break;
   }
}

void LCD_CString_Position(char row, char col, const char *msg)
{
char location = 0;
  switch (row):
    {
    case 1:
     location = (0x80) | ((col) & 0x0F);     // Print message on 1st row and desired location.
     break;
    case 2:
       location = (0xC0) | ((col) & 0x0F);   // Print message on 2nd row and desired location.
       break;
    default:
    break;
    }
    LCD_Write_Cmd(location);
    LCD_Write_String(msg);  //  <-- au lieu de *msg
}


void LCD_String_Position_v2(char row, char col, char *msg)
{
if (row == 1)
    {
     LCD_Write_Cmd((col & 0x0F)|0x80);   // Print message on 1st row and desired location.
    }
else if (row == 2)
    {
     LCD_Write_Cmd((col & 0x0F)|0xC0);      // Print message on 2nd row and desired location.
    }
LCD_Write_String_v2(msg);
}

... main  program...

  Lcd_Init_v3();                                           // Initialize LCD.
  while(1)                                                  // Endless loop.
{
  pointeur_de_char=&texte[0];  // <- au cas ou le pointeur serais altéré
  portc.b2 = 1;
  Lcd_Out(1, 1, "Bonjour ! ");
  strConstRamCpy(pointeur_de_char,"Bonjour !");
  Lcd_Out(1, 1, pointeur_de_char);                   
  LCD_CString_Position(1, 1,"Bonjour !");
  pointeur_de_char=&texte[0];  // <- au cas ou le pointeur serais altéré
  strConstRamCpy(pointeur_de_char,"Bonjour !");
  LCD_String_Position_v2(1, 1, pointeur_de_char);
  Delay_ms(1000);
}

Bonjour Paul,

Thanks so much for your fast and very helpful answer.

I copied / pasted your code. It works. Except one line ...


... main program...

Lcd_Init_v3(); // Initialize LCD. while(1) // Endless loop. { pointeur_de_char=&texte[0]; // <- au cas ou le pointeur serais altéré portc.b2 = 1; strConstRamCpy(pointeur_de_char,"Bonjour !"); LCD_CString_Position(1, 1,"Bonjour !"); pointeur_de_char=&texte[0]; // <- au cas ou le pointeur serais altéré strConstRamCpy(pointeur_de_char,"Bonjour !"); LCD_String_Position_v2(1, 1, pointeur_de_char); }

hello Eric,

*pointer => contenu (char) pointé par le pointeur
pointer => seul = adresse zone pointée

Code:
  unsigned char *pointeur_de_char;         // Déclaration d'un pointeur (*) de char "pointeur_de_char".
  char texte[17]; // pour LCD de 16 chars/ligne
  pointeur_de_char = &texte[0];

// --- Copie le texte depuis FLASH ROM vers RAM

void strConstRamCpy(unsigned char *dest, const code char *source)
{
  while (*source)*dest++ = *source++ ;
  *dest = 0 ;    // terminateur
}

void LCD_Write_CString(const char *msg)                 
{
while ((*msg) != 0)                                          // Send each char of string till the 0.
    {
     LCD_Write_Data(*msg);
     *msg++;  // pointeur msg modifié !
    }
}


void LCD_Write_String_v2(char *msg)        
{
// variante avec pointeur msg non modifié
int k;
k=0;
while( *(msg)>0)
{
    LCD_Write_Data(*(msg+k));   // data pointée par msg+k
    k++;
    if (k>15) break;
   }
}

void LCD_CString_Position(char row, char col, const char *msg)
{
char location = 0;
  switch (row):
    {
    case 1:
     location = (0x80) | ((col) & 0x0F);     // Print message on 1st row and desired location.
     break;
    case 2:
       location = (0xC0) | ((col) & 0x0F);   // Print message on 2nd row and desired location.
       break;
    default:
    break;
    }
    LCD_Write_Cmd(location);
    LCD_Write_String(msg);  //  <-- au lieu de *msg
}


void LCD_String_Position_v2(char row, char col, char *msg)
{
if (row == 1)
    {
     LCD_Write_Cmd((col & 0x0F)|0x80);   // Print message on 1st row and desired location.
    }
else if (row == 2)
    {
     LCD_Write_Cmd((col & 0x0F)|0xC0);      // Print message on 2nd row and desired location.
    }
LCD_Write_String_v2(msg);
}

... main  program...

  Lcd_Init_v3();                                           // Initialize LCD.
  while(1)                                                  // Endless loop.
{
  pointeur_de_char=&texte[0];  // <- au cas ou le pointeur serais altéré
  portc.b2 = 1;
  Lcd_Out(1, 1, "Bonjour ! ");
  strConstRamCpy(pointeur_de_char,"Bonjour !");
  Lcd_Out(1, 1, pointeur_de_char);                    
  LCD_CString_Position(1, 1,"Bonjour !");
  pointeur_de_char=&texte[0];  // <- au cas ou le pointeur serais altéré
  strConstRamCpy(pointeur_de_char,"Bonjour !");
  LCD_String_Position_v2(1, 1, pointeur_de_char);
  Delay_ms(1000);
}

Bonsoir Paul,
Merci beaucoup for your helpful and prompt reply again ! Your modified subroutines are interresting (with switch ... case ...)
I simplify main program here hunder. It runs properly except with LCD_String_Position_v2(1, 0, pointeur_de_char);
With LCD_String_Position_v2(1, 0, pointeur_de_char); LCD display "Bonjour !" with just behind different unreadable symbols like "¥£Æ©∞ªȼ" till the 16th position.
I tried with char texte[17] = ""; instead of char texte[17];
LCD display "Bonjour !ΞΞΞΞΞΞ".
I haven't tried to troobleshoot deeper yet.
All suggestion is welcomed.
Merci beaucoup !
Eric

PS :
What do you mean about "Si le pointeur est altéré ..." ?

Here under the part of the code :

// Essai 11 : Debugging in progress ...

Lcd_Init_v4(); // Initialize LCD.

while(1) // Endless loop.
{
unsigned char *pointeur_de_char;
char texte[17] = "";
pointeur_de_char = &texte[0]; // Si le pointeur est altéré ...
portc.b2 = 1;
strConstRamCpy(pointeur_de_char, "Bonjour !");
//LCD_String_Position(1, 0, "Bonjour !"); // OK.
LCD_String_Position_v2(1, 0, pointeur_de_char); // FAIL.
}
--- Updated ---

@KlausST,

The code that Eric_O posted is one of the better efforts I have seen so far this year.

After creating a microC project for the PIC16F887 and including support from the microC LCD library for a 16x2 LCD module the code compiles without any diagnostic messages (no errors or warnings).

That said there are some errors in Eric_O's implementation.

Some have already been mentioned, but another is much more subtle.

The sequence of commands to get the LCD module in to 4-bit parallel mode will only work one time immediately after the module has been powered on.

Merci Dan1138 !
--- Updated ---

Hi,

If you want us to help you we need something to validate with.
A single source always is correct.
Usually we like to see code and schematic, so we can check if both match.

In post#1 you refer to line numbers, but I don't see line numbers in your sources.

Undocumented code never is a good idea, even not if it is just for yourself.
But posting it in a forum surely reduces feedback.

I've written many ASM programs. I've spent some time to find out what you want to achieve...but it's more difficult on a foreign code than on one owns code.

Klaus

I'm agree with you Klaus.
Concerning schematic, i take schematics on some websites like electronicwings.com or other. Next time I will ad a copy screen of the schematics.
 
Last edited by a moderator:

hello

it seems zero string terminator is not detected ?

try to init texte table with zero values in it.

and modify the test
in void LCD_Write_String_v2(char *msg)

Code:
while( *(msg)>0)
by while( *(msg+k)>0)
because msg itself is not increasing
 

    Eric_O

    Points: 2
    Helpful Answer Positive Rating
hello

it seems zero string terminator is not detected ?

try to init texte table with zero values in it.

and modify the test
in void LCD_Write_String_v2(char *msg)

Code:
while( *(msg)>0)
by while( *(msg+k)>0)
because msg itself is not increasing
Bonjour Paul,
Thanks ! Of course, you are wright. It works now.
Eric
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top