# lcd1602 weird problem

#### bug13

Joined Feb 13, 2012
1,996
Hi guys

I am this LCD here:
http://www.newhavendisplay.com/specs/NHD-C0216CZ-FSW-FBW-3V3.pdf

W
hen it power up, it some time works, some time just show nothing. Say 30-40% of the time it just show nothing on the display.

I believe it's not a hardware problem, as the LCD is on a demo board, and it works fine on their demo firmware.

Here is my code to initialize the LCD: (feel free to ask if more codes is needed)

Code:
void LCD_Initialize(void)
{
LCD_CS = 1;
LCD_RESET = 0;
//DELAY_ms(8);
DELAY_ms(8);
LCD_RESET = 1;
//DELAY_ms(80);
DELAY_ms(20);
LCD_WriteCmd(LCD_WAKEUP);
//DELAY_ms(8);
DELAY_ms(2);
LCD_WriteCmd(LCD_WAKEUP);
LCD_WriteCmd(LCD_WAKEUP);
LCD_WriteCmd(LCD_FUNCTION_SET);
LCD_WriteCmd(LCD_INT_OSC);
LCD_WriteCmd(LCD_PWR_CTRL);
LCD_WriteCmd(LCD_FOLLOWER_CTRL);

LCD_WriteCmd(LCDCMD_CONTRASTSET_LOWBYTE);
LCD_WriteCmd(LCD_ON);
LCD_WriteCmd(LCD_ENTRY_MODE);
LCD_WriteCmd(LCDCMD_CLEARDISPLAY);
DELAY_ms(40);
}

#### MrChips

Joined Oct 2, 2009
24,627
Did you install a 0.1μF capacitor across the power rails at the LCD module?

#### bug13

Joined Feb 13, 2012
1,996
Did you install a 0.1μF capacitor across the power rails at the LCD module?
According the datasheet of the demo board. It has a 0.1uF cap across the power rails at the LCD module. I am guessing its my codes/complier, as the LCD is fine with the demo software. I am using the free version of the XC8 compiler in MPLAP X.

#### takao21203

Joined Apr 28, 2012
3,702
According the datasheet of the demo board. It has a 0.1uF cap across the power rails at the LCD module. I am guessing its my codes/complier, as the LCD is fine with the demo software. I am using the free version of the XC8 compiler in MPLAP X.
Isnt the demo source code included?
Not a compiler issue.

There are a couple of reasons which can lead to problems for these modules.

#### bug13

Joined Feb 13, 2012
1,996
Hi

Yes I am using the demo source code. And it happens to the demo source code too.

#### takao21203

Joined Apr 28, 2012
3,702
Try powering on the LCD through IO after some waiting, with all the lines set as output + correct state.

#### JohnInTX

Joined Jun 26, 2012
4,601
Are you waiting >40ms after Vcc stable before sending commands?
E line pulled low external to the uC to avoid spurrious commands while the uC is in RESET?
Have you checked the detailed init sequences in the ST7032 controller's datasheet?

If you do the init properly, the display will come up and run. You don't need to power it from the IO. The fact that it runs properly with the demo code confirms this.

Which uC are you using?

Good luck!

EDIT: be sure your compiler knows what your clock frequency is so that it can compute the delays accurately.

Also, note that there is a >26.3 uS delay called out between each instruction during init (and probably between displayed characters as well). You don't have any explicit delay between many of these. If the LCD output routines poll the busy flag you are good but only after the 2ed or 3rd Function-Set. You need delays between these always. If not checking busy be sure that the execution time between the LCD_WriteCmd instructions is long enough to generate the >26.3us or add delays between them.

Last edited:

#### bug13

Joined Feb 13, 2012
1,996
Hi guys

Thanks for all your inputs, after reading all replies and trying a few things, the following works, thanks JohnInTX for pointing this out:

Code:
void LCD_Initialize(void)
{
LCD_CS = 1;
LCD_RESET = 0;
//DELAY_ms(8);
DELAY_ms(8);
LCD_RESET = 1;
//DELAY_ms(80);
DELAY_ms(20);
LCD_WriteCmd(LCD_WAKEUP);
//DELAY_ms(8);
DELAY_ms(2);
LCD_WriteCmd(LCD_WAKEUP);
DELAY_ms(1);
LCD_WriteCmd(LCD_WAKEUP);
DELAY_ms(1);
LCD_WriteCmd(LCD_FUNCTION_SET);
DELAY_ms(1);
LCD_WriteCmd(LCD_INT_OSC);
DELAY_ms(1);
LCD_WriteCmd(LCD_PWR_CTRL);
DELAY_ms(1);
LCD_WriteCmd(LCD_FOLLOWER_CTRL);
DELAY_ms(1);
LCD_WriteCmd(LCDCMD_CONTRASTSET_LOWBYTE);
DELAY_ms(1);
LCD_WriteCmd(LCD_ON);
DELAY_ms(1);
LCD_WriteCmd(LCD_ENTRY_MODE);
DELAY_ms(1);
LCD_WriteCmd(LCDCMD_CLEARDISPLAY);
DELAY_ms(40);
}

#### JohnInTX

Joined Jun 26, 2012
4,601
Well done.

Now.. if you are not polling the busy flag, write your character out routine to ensure that it takes at least 30uS (from the example in the controller's datasheet) between characters. For 30uS, I'd probably just do some housekeeping (bump a pointer to the next character etc.) and make sure it took at least 30uS to execute - maybe add an inline assembler delay to make up any difference. I'd try to avoid the 1ms delay between chars if possible. I don't like burning any more CPU time than I have to. Eventually, it always seems to come back and bite me.

I find things in this time range problematic - you don't want to use a 1ms delay for 30uS intervals. An interrupt-driven timer for 30uS delay would essentially be a dumb delay because the interrupt service latency would likely take the 30uS anyway so I'd just try to do whatever housekeeping I could towards using up 30uS and burn the few uS left in NOPs or some other short delay.

Looks good, though. Have fun.

Last edited:

#### bug13

Joined Feb 13, 2012
1,996
Well done.

Now.. if you are not polling the busy flag, write your character out routine to ensure that it takes at least 30uS (from the example in the controller's datasheet) between characters. For 30uS, I'd probably just do some housekeeping (bump a pointer to the next character etc.) and make sure it took at least 30uS to execute - maybe add an inline assembler delay to make up any difference. I'd try to avoid the 1ms delay between chars if possible. I don't like burning any more CPU time than I have to. Eventually, it always seems to come back and bite me.

I find things in this time range problematic - you don't want to use a 1ms delay for 30uS intervals. An interrupt-driven timer for 30uS delay would essentially be a dumb delay because the interrupt service latency would likely take the 30uS anyway so I'd just try to do whatever housekeeping I could towards using up 30uS and burn the few uS left in NOPs or some other short delay.

Looks good, though. Have fun.
Thanks for your help. I will change my code to poll the busy flag. The above code just something quick and dirty to get it working. Thanks a lot!