I've been trying to interface with a HD44780 compatible display (16x2) for quite a few hours now, but have run into some weird behavior problems which I can't solve.

My setup:

  • I'm using the LCD in 4-bit mode (the upper four bits, D4-D7, as in all the guides I've found, the order is correct - I've checked a few times).
  • The LCD is running from a 5v regulated supply. (I've tried 3.3v, same result, less contrast)
  • The R/W line is grounded with a pull-down resistor (fixed in write mode).
  • The contrast is set by a pot and I can get the one line of squares visible at startup.
  • I'm using very slow timings (~200ms wait - enable high - ~200ms - change data - ~200ms - enable low)

My init sequence:

(with RS low)

  • 0x03 - (three times) (sent as one nibble/byte)
  • 0x02 - Enable four bit mode (sent as one nibble/byte)
  • 0x28 - Function set (2 line, 4 bit) (sent as two nibbles, ms nibble first)
  • 0x01 - Clear (sent as two nibbles)
  • 0x06 - Set entry mode (increment cursor on write, no display shift) (sent as two nibbles)
  • 0x08 - Display, cursor and blink off (sent as two nibbles)
  • 0x0F - Display, cursor and blink on (sent as two nibbles)

Here, some things don't happen as expected:

  • Two line mode doesn't seem to enable (no dark background squares on second line, no chars get written there)
  • Clear doesn't happen
  • The cursor is in the 3rd square instead of the first at the end of this init sequence

Next I try to write some characters with RS high, sending 2 nibbles per character.

Here too, I get weird behavior: Instead of writing 1 character per 2 nibbles, it writes 2 (one per nibble). I made it go through the chars 0-15 and I get random symbols (eg slash) and Japanese chars. All of them are from random places on the char table, mostly the bottom row, not in any normal order, but always the same chars in the same order get printed.

My question: I've really run out of ideas to fix this. Am I missing anything obvious? What problems could I be having and how can I debug further?

Edit: This is what I see on my screen after init, it may be helpful LCD after init

Edit 2:

My main code:

GPIOPin lcdEnablePin = PIN_B(11);
GPIOPin lcdRSPin = PIN_B(10);
GPIOPin lcdDataPins[] = {PIN_E(2), PIN_E(3), PIN_E(4), PIN_E(5)};

//Set all pins as outputs
GPIO::pinModeDigital(lcdEnablePin, 1);
GPIO::pinModeDigital(lcdRSPin, 1);
for(int i = 0; i < 4; i++)
 GPIO::pinModeDigital(lcdDataPins[i], 1);

GPIO::writePinDigital(lcdRSPin, 0); //Instruction register
lcdSendData4(lcdEnablePin, lcdDataPins, 2); //Enable 4 bit
lcdSendData8(lcdEnablePin, lcdDataPins, 40); //Function set, 2 line
lcdSendData8(lcdEnablePin, lcdDataPins, 1); //Clear and return home
lcdSendData8(lcdEnablePin, lcdDataPins, 2); //Entry Mode, Increment cursor position, No display shift
lcdSendData8(lcdEnablePin, lcdDataPins, 8); //All off
lcdSendData8(lcdEnablePin, lcdDataPins, 15); //All on

GPIO::writePinDigital(lcdRSPin, 1); //Data register
for(int i = 0; i < 16; i++) //Write test data, 4 bit because that's what seemed to work
 lcdSendData4(lcdEnablePin, lcdDataPins, i);

My SendData functions:

void lcdSendData4(GPIOPin lcdEnablePin, GPIOPin lcdDataPins[], char data)

 //Set enable high
 GPIO::writePinDigital(lcdEnablePin, 1);


 //Write data
 for(int i = 0; i < 4; i++)
  GPIO::writePinDigital(lcdDataPins[i], data & (1 << i));


 //Falling edge
 GPIO::writePinDigital(lcdEnablePin, 0);

void lcdSendData8(GPIOPin lcdEnablePin, GPIOPin lcdDataPins[], char data)
 lcdSendData4(lcdEnablePin, lcdDataPins, data >> 4); //Send MSB
 lcdSendData4(lcdEnablePin, lcdDataPins, data); //Send LSB
  • \$\begingroup\$ Do you have a sufficiently long wait before starting to write? And what value is the "pull down" resistor? \$\endgroup\$ Commented Aug 20, 2014 at 17:18
  • \$\begingroup\$ Did you follow the timing in the datasheet? \$\endgroup\$ Commented Aug 20, 2014 at 17:18
  • \$\begingroup\$ Sphero: The resistor is 1k \$\endgroup\$
    – tehwalris
    Commented Aug 20, 2014 at 17:21
  • \$\begingroup\$ Ignacio: I don't have a datasheet for my particular LCD, but the delays I'm using are well over the max times specified in the HD44780 datasheet. Like I said in the question, I spend around ~200ms with enable high, ~200ms while data is written and ~200ms after the falling edge of enable. \$\endgroup\$
    – tehwalris
    Commented Aug 20, 2014 at 17:23
  • 4
    \$\begingroup\$ The characters are not random at all. They all have lower four bits at 1 1 1 1. I would say you are in 8 bit mode and the lower nibble is sensed from air. Try touching the D[0..3] pads with your finger and see if the characters change. \$\endgroup\$
    – venny
    Commented Aug 20, 2014 at 20:10

4 Answers 4


On some models you need to send the initial setup commands multiple times. Also some models that I have consume power in an aggressive, pulsed way, so have a large capacitor close to the power supply (+ -) of the LCD to avoid power rail noise.


You have not mentioned the E line so far.

E needs to be low, then present data, set E high then low etc.

  • 1
    \$\begingroup\$ Welcome to the forum! And yes, he did. It is at the fifth bullet (11th line). \$\endgroup\$
    – venny
    Commented Aug 20, 2014 at 19:22
  • \$\begingroup\$ Yeah, as mentioned in the question that's what I do, with 200ms delays between each step. \$\endgroup\$
    – tehwalris
    Commented Aug 20, 2014 at 19:40

Have you allowed for the necessary delays for the initialisation? Data-sheet says you have to wait for more than 4.1 ms after sending the first 0x3.

  • 3
    \$\begingroup\$ Welcome to EE.SE. We are a Q/A kind of site rather than a forum. You've posted an answer that would be better suited as a comment to the question. In the future, please try to keep in mind that answers are for larger, more involved assistance. \$\endgroup\$
    – Funkyguy
    Commented Jan 2, 2015 at 17:34
  • 1
    \$\begingroup\$ @Funkyguy IIRC StackExchange does not allow users with less than 15 point rep to comment, only answer. chamod probably did all the site allowed him to at the time. (that wasn't very long ago in my case :) \$\endgroup\$ Commented May 25, 2015 at 11:40

I got some display once with similar behavior. I needed to set it to 8-Bit mode three times and than once more set it to 4 bit mode to bring it "really" to 4 bit mode. This was the only way I got it to work in 4-Bit mode. Maybe this helps.

  • 1
    \$\begingroup\$ When the display is in 4-bit mode, the only thing that distinguishes between the top and bottom half of each transaction is whether there have been an even or odd number of transactions since the display was switched to 4-bit mode. Switching to 8 bits and then back lets software and the display get in sync with each other. \$\endgroup\$
    – supercat
    Commented Jun 1, 2016 at 21:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.