[SOLVED] Not printing the character in the Specified location in the LCD

Status
Not open for further replies.

jack1998

Junior Member level 2
Joined
Oct 17, 2021
Messages
20
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
136
I have connected the LCD with the microcontroller 8051. I have used 16x2 LCD where D4_D8 are used for I/O and connected to the microcontroller port P7. I want to print each character in the specified location of the LCD. The connection works fine. I am new to the microcontroller, I am trying to know the LCD interface with the microcontroller. But, when I try to print the character in the specified line, it is printing in the wrong location. Help me? Thank you!

Code:
        #include <stdio.h>
        #include <string.h>            

        unsigned char one[2] = "A";
        unsigned char one1[2] = "B";
        unsigned char one12[2] = "c";
         
          void lcd_init(void)
            {
              P7 = 0x00;        //E=0,RS=0

              P7 = 0x03;
              P7 = 0x23;        //E=1,RS=0
              delay_micro(100);
              P7 = 0x03;        //E=0,RS=0
              delay_msec(5);
              P7 = 0x23;        //E=1,RS=0
              delay_micro(100);
              P7 = 0x03;        //E=0,RS=0
              delay_msec(5); 
              P7 = 0x23;        //E=1,RS=0
              delay_micro(100);
              P7 = 0x03;        //E=0,RS=0
              lcd_cout(0x02);              //for 4-bit lcd intialization
              delay_msec(5);
              lcd_cout(0x28);       
              delay_msec(5);
              lcd_cout(0x0C);
              delay_msec(5);                    
          }
              int lcd_cout(unsigned char ccod)           //for Lcd command
          {
              unsigned char ccod_msb;
              unsigned char ccod_lsb;

              ccod_msb = ccod / 0x10;
              ccod_lsb = ccod & 0x0F;
              P7 = ccod_msb;                

              P7 = ccod_msb | 0x20;          
              delay_micro(2);
              P7 = ccod_msb;        
              delay_micro(2);
              P7 = ccod_lsb;    
              P7 = ccod_lsb | 0x20; 
              delay_micro(2);
              P7 = ccod_lsb;        
              delay_micro(50);
              return 0;
               }
              int lcd_dout(unsigned char dcod)            //for lcd_Data
                     {
               unsigned char dcod_msb;
               unsigned char dcod_lsb;

               dcod_msb = dcod / 0x10;
               dcod_lsb = dcod & 0x0F;

               P7 = dcod_msb | 0x10;    

               P7 = dcod_msb | 0x30;    
               delay_micro(2);
               P7 = dcod_msb | 0x10;    
               delay_micro(2);
               P7 = dcod_lsb | 0x10;        
               P7 = dcod_lsb | 0x30;    
               delay_micro(2);
               P7 = dcod_lsb | 0x10;    
               delay_micro(50);     
           }

           void main()
              { 
             while (1)
                {
                  lcd_init();
                  display1();
                }
            }

         void display1(void)
          {                         
            write_string(0, 7, one); 
            delay_msec(100);
            write_string(1, 0, one1); 
            delay_msec(100);  
            write_string(1, 7, one12); 
            delay_msec(100);   
         }

        void write_string(uint_fast8_t row, uint_fast8_t col, unsigned const char  *str) {
                int x,y;                                             
             if (row)
                    {
                    col |= 0x40;                    
                } 
                col |= 0x80;
                lcd_cout (col); 

                for (x=0; x!=0; x++) {      
                      lcd_dout(one[x]); 
                      delay_msec(5);  
                      lcd_dout(one1[x]);
                      delay_msec(5); 
                      lcd_dout(one12[x]);
                 }                  
           }
 

Hi,

According your description the position of the text is wrong. So position is important. And for debugging it's important to know what happens.
So instead writing "in wrong location" you should precisely say at which location. This gives us an idea whether there is a bit shift problem, a connection problem, a timing problem...or other problem.
--> focus on the problem

* Usually LCD_INIT needs to be done only once, thus don't do it in a WHILE loop, where it is performed over and over again.

* For debugging it's not good to do the "display1" in an (not timing controlled) loop either.
It's simply too fast for the eyes and the brain to detect whats really going on.

--> so move both functions before the WHILE loop.
Within the while loop you may just put (only for debugging)
* delay 5 seconds
* display another text at a different position
* delay again 5 seconds
* do the init
..close loop

Then you and we are able to detect whether it's a
* power up problem (test at true power up, do another test by pressing RESET)
* or an init problem
The 5 second delay helps you to see what really happens on the display..step by step...

Klaus
 

The code had arbitrary modifications, e.g. write_string() is not outputting variable str. Before starting to guess how the original code should look like, I would at least expect an error description, what is actually printed?
--- Updated ---

Specifically: Is the lcd correctly initialized with 2 rows and auto cursor increment? What's the effect of set cursor commands?
 

@KlausST Isn't it the correct way for positioning?
write_string(0, 7, one);

As specified above code, I want to write in that location but it's printing all ABC in all locations (0,7), in (1,7), in (1,0). Means In (0,7) it writes ABC, also in (1,7), it writes ABC and so on.

I don't get this line?
For debugging it's not good to do the "display1" in a (not timing controlled) loop either.
How should I do?
 

@FvM Its, not the modification, it is the code I have used.
In the write_string() function, the parameter string(str) is passed so that In the display function I can pass the argument, Is there another way to do the same?

yeah, the LCD correctly initialized with 2 rows and auto cursor increment.
when I use this function to set the cursor and used to test to make blinking in the specified location it starts blinking :
Code:
void set_cursor_position (uint_fast8_t row, uint_fast8_t col)                                                 
           {              
          if (row)
                        {
                        col |= 0x40;                    
                    } 
                    col |= 0x80;
                    lcd_cout (col);  
                 
           }   
calling the function as:
          set_cursor_position (1, 0);
          lcd_cout(0x0f);
 

Hi,

Quite expectable ...
As written it is not a way to solve the problem but to find the problem. (Powerup, reset, init....)

Still we miss clear information how it behaves ....

Klaus
 

but it's printing all ABC in all locations (0,7), in (1,7), in (1,0). Means In (0,7) it writes ABC, also in (1,7), it writes ABC and so on.
That's exactly what you have coded in write_string().
Review your code. str is never referenced in write_string(), instead it prints the three constants.
Try
Code:
while (*str) lcd_dout(*str++);
instead of the for next loop.
 

    jack1998

    Points: 2
    Helpful Answer Positive Rating
Hello!

Remarks about your code:
1. It's not commented at all, therefore not easy to read. Instead of commenting repeatedly
// E= xx, RS = xx, why not using definitions?
For instance, in case it's indeed the right value:
#define LCD_E 0x20
Similarily define LCD_RS and use it directly in your functions.

2. Don't divide if you want to bit shift.
ccod_msb = ccod / 0x10;
Write instead:
ccod_msb = ccod >> 4; // Right shift by 4.

Similarily, don't shift if you want to divide. All compilers these days know that dividing
by a power of 2 is a shift, so you don't gain anything by shifting. NB: you don't need this
remark for the present code.

3. Use constants.
#define LCD_DELAY 100
delay_micro(LCD_DELAY);
If you need to change the delay, you have to change only once.
and since you also have another delay, define one second delay, call it LCD_DELAY2 or better:
#define LCD_DELAY_INIT 100
#define LCD_DELAY_WR 50
etc...

4. You could also consider having one single function for LCD access. Your lcd_cout and
lcd_dout are basically the same, they differ by one bit only. And use it like this:
lcd_write(CMD, val);
lcd_write(DAT, val);

5. When you write:
for(x = 0 ; x != 0 ; x++)
what do you think it will do?
i.e. you tell the compiler to start at 0, and do something as long as x is not 0. Are you sure
of what you are writing?

Dora.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…