LCD damaged?

Thread Starter

winson

Joined Dec 3, 2008
23
Hi everybody,

I was trying to write a simple LCD testing program to display "P" on 1st line and display "L" on the 2nd line, but my 16x2 LCD just show 2 line of grey square. I was using the Port C & Port D of my PIC16F877A and using 8-bits interface to display character on my LCD. I also try to put a pullup resistor to all the port's pins that used but the results is still the same. The 8 data pins of the LCD is connect to Port D and RS, RW, E is connect to the first 3 pins(RA0, RA1, RA2) of Port C.

I was using CCS C compiler, to write this testing program i was refer to the information provided in the HD44780U datasheet.

Anybody can give some suggestions regarding the error that i have make?
The testing program is shown below.

Any suggestion will be greatly appreciate.
Thanks.

Rich (BB code):
#include <16F877A.h>
#fuses hs, nowdt, nolvp, noprotect   //Config
#use delay (clock = 20000000)      //20MHz Crystal

void init(void);      //Function Prototype
void busy_test(void);
void display(void);
void send_command(void);
void send_data(void);

unsigned char PORTC, TRISC, PORTD, TRISD, RS, RW, E, BF;
unsigned char command, data;

#byte PORTC = 0x07
#byte TRISC = 0x87
#byte PORTD = 0x08
#byte TRISD = 0x88

#bit RS = PORTC.0
#bit RW = PORTC.1
#bit E  = PORTC.2
#bit BF = PORTD.7

void main()
{
   init();
   display();
   while (1)
   {

   }   
}

void init()
{
   PORTC = 0x00;   //Clear Port C
   PORTD = 0x00;   //Clear Port D

   TRISC = 0x00;   //Set Port C As Output
   TRISD = 0x00;   //Set Port D As Output

   delay_ms (500);   //Power-On Delay
         //Busy Flag Valid Here

   //busy_test();   //Check Busy Flag
   command = 0x38;   //8-Bits, 2-Lines, 5x7 Dots
   send_command();   //Send Command To LCD

   delay_ms (10);

   //busy_test();   //Check Busy Flag
   command = 0x38;   //8-Bits, 2-Lines, 5x7 Dots
   send_command();   //Send Command To LCD

   delay_us (500);

   //busy_test();   //Check Busy Flag
   command = 0x38;   //8-Bits, 2-Lines, 5x7 Dots
   send_command();   //Send Command To LCD

   delay_ms (1);

   busy_test();   //Check Busy Flag
   command = 0x38;   //8-Bits, 2-Lines, 5x7 Dots
   send_command();   //Send Command To LCD

   delay_ms (1);

   busy_test();   //Check BF
   command = 0x08;   //Display Off, Cursor Off, No-Blink
   send_command();   //Send

   delay_ms (1);

   busy_test();
   command = 0x01;   //Clear Display
   send_command();

   delay_ms (5);

   busy_test();
   command = 0x06;   //Increment Cursor Position, No-Shift
   send_command();

   delay_ms (1);

   busy_test();
   command = 0x0F;   //Display On, Cursor On, Blink
   send_command();

   delay_ms (1);
}


void display()
{

   busy_test();
   command = 0x80;   //Set DDRAM Address To 0x00
   send_command();

   delay_ms (1);

   busy_test();
   data = 0x50;   //Display "P"
   send_data();

   delay_ms (1);

   busy_test();
   command = 0xC0;   //Set DDRAM Address To 0x40
   send_command();

   delay_ms (1);

   busy_test();
   data = 0x4C;   //Display "L"
   send_data();

   delay_ms (1);

}


void busy_test()
{
   while (1)
   {
      TRISD = 0xFF;      //Set Port D As Input
      //RS = 0;            //Command
      //RW = 1;            //Read Busy Flag
      PORTC = 0x02;

      delay_cycles (2);   //Control Setup Time
      //E  = 1;            //E-Line High
      PORTC = 0x06;

      delay_cycles (6);   //Wait Data Return

      if (BF == 0)
      {
         TRISD = 0x00;   //Set Port D Back To Output
         //E  = 0;         //E-Line Low
         PORTC = 0x02;
         return;
      }

      //E  = 0;            //E-Line Low
      PORTC = 0x02;
   }      //End while loop
}      //End Function


void send_command()
{   
   //RS = 0;            //Command
   //RW = 0;            //Write Instruction
   PORTC = 0x00;

   delay_cycles (2);   //Control Setup Time
   //E  = 1;            //E-Line High
   PORTC = 0x04;

   delay_cycles (3);   
   PORTD = command;   //Put Command To Port D

   delay_cycles (3);   //Data Setup Time
   //E  = 0;            //E-Line Low
   PORTC = 0x00;
   delay_cycles (1);   //Control & Data Hold Time
}


void send_data()
{
   //RS = 1;            //Data
   //RW = 0;            //Write data
   PORTC = 0x01;
   
   delay_cycles (2);   //Control Setup Time
   //E  = 1;            //E-Line High
   PORTC = 0x05;

   delay_cycles (3);
   PORTD = data;      //Put Data To Port D

   delay_cycles (3);   //Data Setup Time
   //E  = 0;            //E-Line Low
   PORTC = 0x01;
   delay_cycles (1);   //Control & Data Hold Time
}
 

Thread Starter

winson

Joined Dec 3, 2008
23
The problem is in the power supply. The 5V Vdd supply voltage drop to 4.33V when it is connect to the LCD. I was using a battery for the LCD, due to high supply current of the 9V battery, thus have to put a current limiting resistor to limit the current that goes into the LCD, And i think because of the LCD consist of certain amount of internal resistance(from calculation it is around 23.23K ohms), this resistance will form a voltage divider with my current limiting resistor and make the supply voltage to the LCD drop to 4.33V. Normally, for LCD it's Vdd range is from 4.5V to 5.5V in order for it to work correctly.

After adjust the value of the current limiting resistor to get back a Vdd which is around 4.6V then the LCD work nicely. Besides, for the Vo of the LCD i was directly connect it to ground to get maximum contrast, this is to avoid the variable resistor(pot) that use to control the contrast from disturbing the voltage value of the Vdd.

For the send_command() and send_data() function i was modify the code to first load the data to the Port D then toggle the E signal from low to high then goes back to low again. I think it also work by set the E signal to high first then load data to Port D and after that set E to low, but since the LCD is working then i will follow the modified code.
 

NavjeetSingh

Joined Feb 8, 2009
9
Thanks for the second post. I never knew that the LCD resistance could be such a big problem. You have explained it quite well, giving the numerical details along with explanation.

Would you please take the pain of explaining the way you did troubleshooting. I always get stuck whenever I'm asked to do troubleshooting. Would you name the instruments too (those you used to troubleshoot).
 

Thread Starter

winson

Joined Dec 3, 2008
23
Thanks for the second post. I never knew that the LCD resistance could be such a big problem. You have explained it quite well, giving the numerical details along with explanation.

Would you please take the pain of explaining the way you did troubleshooting. I always get stuck whenever I'm asked to do troubleshooting. Would you name the instruments too (those you used to troubleshoot).
Hi NavjeetSingh,

To troubleshoot my LCD problem, i was not using many instruments just my tiny digital multimeter. During that first time when problem occur, a 3.3K ohms current limiting resistor was connected in series with the Vdd pin of the LCD and what i doing is just use the multimeter to measure the voltage in the point between the 3.3k resistor and Vdd of LCD with respect to ground and the value that i get is 4.33V which insufficient for a typical LCD display. Then i just using the formula of the voltage divider rule to calculate out the resistance of the LCD by just assume we have 2 resistors, one is the 3.3k another one is the LCD resistance. To obtain the correct value of the current limiting resistor i was just using the voltage divider rule again with LCD resistance value(23.23k) that i calculated just now to calculate out the value of the current limiting resistor which can give 4.6V and 2.5mA. For a typical LCD it need 4.5V to 5.5V and around 3mA of current to it's Vdd pin.
 
Last edited:
Top