4
\$\begingroup\$

I've been trying to get my LCD initialized for about a week now, and am quite embarrassed to say that I've been unsuccessful thus far. I've done this in the past, and I remember it being a little tricky getting the initialization sequence just right, but at this point I think I've fully vetted the implementation and it's just not working.

Setup:

  1. NHT-C0220AZ-FSW-FTW LCD with an NT7605 driver
  2. TI Launchpad w/ MSP430G2231
  3. single-turn 10k pot for contrast control
  4. LCD powered with 3.3V
  5. Launchpad powered with USB
  6. Grounds for each component tied together
  7. using the LCD's 4bit interface
  8. LCD backlight connected to Vcc (3.3V) from Launchpad

enter image description here

Here are things I have done so far for testing:

  1. Double checked connections
    1. LCD pins D4-D7, RS, R/W, and E
    2. Potentiometer hooked up to contrast control pin, and I have verified that the voltage goes from 0 - Vdd.
    3. LCD Vdd hooked up to 3.4V, which is at about the minimum voltage spec
  2. Double checked I/O routines on MSP430
    1. LCD pins are reset/set as expected as I step through my code
    2. Timing routines are semi "calibrated" for loops
  3. Cross checked documentation for initialization routines against others' routines that I have found online
      1.

Yet after all of this, I can't get anything to display on the LCD! So here are my questions:

  1. The manufacturer has verified that there is a bug in the NT7605 where the busy bit isn't asserted properly. So I have been using fixed delays (fine with me), but wanted to use the busy flag to see if the driver is even responding to commands. Is there another way for me to do a low-level diagnostic to see what the LCD is thinking as I send initialization commands?
  2. Has anyone else here used the same LCD? All other standard LCDs I've used (2x20 character types) darken noticeably when I turn the contrast adjustment, and IIRC they do this even when not initialized properly. However, when I turn the pot on mine, the LCD doesn't darken at all. Perhaps this is because it's not initialized, but I'm not sure.
  3. Can anyone find something screwy with this initialization routine?
    1. delay > 30ms
    2. send 0x20, upper nibble only
    3. send 0x28 (set 4 bit interface)
    4. wait 10ms
    5. send 0x0C (display on, cursor off, blink off)
    6. wait 10ms
    7. send 0x01 (clear display)
    8. wait 10ms
    9. send 0x02 (increment cursor, no display shift)
    10. wait 10ms
    11. set RS high to start sending character data
    12. send 0x48 (display 'H')

Initialization routine from the manufacturer

My code looks like this:

void InitializeLcd()
{
    DelayTicks( 10000);
    // 4 bit interface, 2 lines, 5x8 characters
    // the spec sheet shows the 0x20 part of 0x28 getting sent an extra time
    // so I used a special function to deal with this case.  This just sends
    // the 0x20 part and ignores the 0x08 part.
    SendLcdUpperNibble( COMMAND, 0x28);
    SendLcdByte( COMMAND, 0x28);
    DelayTicks( 1000);
    // Display on, cursor off, blink off
    SendLcdByte( COMMAND, 0x0C);
    DelayTicks( 1000);
    // clear display
    ClearLcd();
    // Entry mode set - increment cursor, no display shift
    SendLcdByte( COMMAND, 0x02);
    DelayTicks( 1000);
    // Set write to DDRAM mode since we'll just be sending data from now on
    SendLcdByte( DATA, 0x48);
    SendLcdByte( DATA, 0x65);
    SendLcdByte( DATA, 0x6C);
    SendLcdByte( DATA, 0x6C);
    SendLcdByte( DATA, 0x6F);
}

void ClearLcd()
{
    // Clear display
    SendLcdByte( COMMAND, 0x01);
    DelayTicks( 1000);  
}

void SetRS( int value)
{
    if( value == 0)
        P2OUT &= ~RS;
    else
        P2OUT |= RS;
}

void SetRW( int value)
{
    if( value == 0)
        P2OUT &= ~RW;
    else
        P2OUT |= RW;    
}

void SetE( int value)
{
    if( value == 0)
        P1OUT &= ~E;
    else
        P1OUT |= E;
}

void DelayMs( int delay)
{
    int ctr;
    int ms = delay * 100;
    for( ctr=0; ctr<ms; ctr++);
}

void DelayTicks( int ticks)
{
    int ctr;
    for( ctr=0; ctr<ticks; ctr++);
}

void SendLcdByte( unsigned char command_0_or_data_1, unsigned char command)
{
    SendLcdUpperNibble( command_0_or_data_1, command);
    // send the lower nibble next
    // special thank you to ToyBuilder for catching my missed bit-shift in the following line
    // I also had the mask on P1OUT incorrect, presumably because I messed up the command mask and just made it match that.
    P1OUT = ((command & 0x0F) << 4) | (P1OUT & 0x0F);
    Strobe( command_0_or_data_1);
}

void SendLcdUpperNibble( unsigned char command_0_or_data_1, unsigned char upper_nibble)
{
    P1OUT = (upper_nibble & 0xF0) | (P1OUT & 0x0F);
    Strobe( command_0_or_data_1);
}

void Strobe( unsigned char command_0_or_data_1)
{
    SetRS( command_0_or_data_1);
    SetRW( 0);
    DelayTicks( 1000);
    SetE( 1);
    DelayTicks( 1000);
    SetE( 0);       
}

The only thing I can say is that the LCD looks like it flickers when I step over SendLcdByte and am sending it character data. When I scope everything, it sure looks like I'm flipping bits properly...

EDIT -- I soldered up a new LCD, and this time I tried leaving the unused data pins (D0-D3) disconnected (i.e. floating). There was no difference. The LCD still flickers when I initialize. I am now waiting 100ms for all delays, including a delay when strobing E. I have also disconnected Vcc coming from the Launchpad FET section and am now just powering the MSP430 and LCD from my lab power supply.

EDIT #2 -- I went to a 3.3V LCD and everything magically started working. Thanks to ToyBuilder for catching a stupid code bug when I was debugging with the 5V LCD. After the swap the LCD initialized properly. I'm currently displaying garbage instead of "Hello", but that's unrelated to this question.

EDIT #3 -- found my display bug -- I was sending 0x06 for entry mode instead of 0x02. Not sure why I did that, must have been a typo.

\$\endgroup\$
  • \$\begingroup\$ A small side note -- If I had known I was going to use the MSP430 for this project, I would have picked out a more suitable LCD, like the NHD-C0220AU-FSW-FTS, which is a 3.3V part. I'm not sure if part of my issue stems from using 3.3V logic signals to bitbang the data bus. I might order one of these LCDs now because I'm wasting too much time on this. \$\endgroup\$ – Dave Apr 19 '11 at 13:35
3
+50
\$\begingroup\$

Oh, duh, I didn't read your code carefully -- your send SendLcdByte is wrong:

    void SendLcdByte( unsigned char command_0_or_data_1, unsigned char command)
{
    SendLcdUpperNibble( command_0_or_data_1, command);
    // send the lower nibble next
 // AS WRITTEN:
    P1OUT = (command & 0x0F) | (P1OUT & 0xF0);
 // SHOULD BE:
    P1OUT = ((command & 0x0F) << 4) | (P1OUT & 0xF0);
    Strobe( command_0_or_data_1);
}
\$\endgroup\$
  • \$\begingroup\$ Great catch! Thank you for finding that -- I totally thought things were working with my bit twiddling but I overlooked the lower byte during testing. I'm pretty sure this is the cause of the problem, and will test soon. \$\endgroup\$ – Dave Apr 25 '11 at 13:09
  • \$\begingroup\$ When I find extra time, I'll have to use the scope on the lower nibble. I thought for sure this fix would have made everything work, but the LCD still isn't initializing. Thanks again for catching my mistake! I completely missed that every time I looked at the code... really embarrassing. :) \$\endgroup\$ – Dave Apr 25 '11 at 13:20
  • \$\begingroup\$ ok, should actually be P1OUT = ((command & 0x0F) << 4) | (P1OUT & 0x0F); I wish I could make an excuse, like "I'm dyslexic", but I can't. I've verified the data bus bits on the scope, but need to re-verify the bits that get strobed because it's still not working. I'm now probing on the LCD itself, rather than poking the breadboard. \$\endgroup\$ – Dave Apr 25 '11 at 13:38
  • \$\begingroup\$ @ToyBuilder: FYI, after switching LCDs, my code is working, but your answer was certainly a key ingredient in getting there. I don't know why this didn't work with the 5V LCD, because my logic levels were within the specs. Anyhow, I decided to restart the bounty, and tomorrow I will award it to you for this answer. Thanks again! \$\endgroup\$ – Dave Apr 27 '11 at 14:28
  • \$\begingroup\$ It may have to do with the ability of the LCD controller to generate the appropriate drive voltage for the liquid crystal in the device -- it might be that at 3.3V, the LC is not getting sufficiently biased to make a visible difference... \$\endgroup\$ – Toybuilder Apr 27 '11 at 18:54
2
\$\begingroup\$

Double check the signal high/low output voltages from the MSP430, and the minimums for the inputs on the LCD.

One other thing is whether you are bit banging too fast -- your source listing doesn't show how you're twiddling the data and E signals. If you twiddle E too soon after loading the data bits, it won't work. If you are not holding E long enough for the LCD to latch the incoming data, it won't work. Try adding a time delay between writing D0-D7, and then between asserting and then deasserting the E line.

I'm assuming the lines are used strictly for the LCD's, so that there's no hold-time issue. If you are using the lines as a bus to other devices as well, you'll need to make sure your data is held long enough before the bus is used for other things.

\$\endgroup\$
  • \$\begingroup\$ thanks for the point about delays after setting the data bits. My code shows the delay that I'm using, which is none. :) I only have a delay of 1000 ticks between E high and E low, which equals about 10ms according to my oscilloscope. I'll give the delay before strobing E a try now. \$\endgroup\$ – Dave Apr 19 '11 at 20:43
  • \$\begingroup\$ MSP430 output level is Vcc-0.3V, so that's 3V. The LCD has a min input high of 2.4V, so I should be good to go. I set the delays to 100ms for everything, and the LCD still just flickers during init and doesn't show me anything. \$\endgroup\$ – Dave Apr 19 '11 at 21:09
  • \$\begingroup\$ I need to understand this part better. From what I can tell, the MSP430 outputs are within spec for the LCD input logic high levels, but tech support thinks that the contrast is the issue. \$\endgroup\$ – Dave Apr 24 '11 at 3:30
1
\$\begingroup\$

Also one thing that tricked me one time was the backlight being so low I couldn't see that it was working.

\$\endgroup\$
  • \$\begingroup\$ Yeah, I definitely have the backlight working! It's bright. The one thing that concerns me is that when I twist the contrast knob, I don't see any visual indication that it's working, and tech support has told me that I should see blocks appear on the first line. \$\endgroup\$ – Dave Apr 21 '11 at 0:05
  • \$\begingroup\$ And it looks like you've tested that your contrast pot not broken...weird. \$\endgroup\$ – kenny Apr 21 '11 at 0:14
  • \$\begingroup\$ Yes, I've watched the voltage swing when I turn it. \$\endgroup\$ – Dave Apr 21 '11 at 2:04
0
\$\begingroup\$

Newhaven Display tech support has recommended that I replace the LCD and try again. It's possible that I damaged it during the initial setup, so we'll see how that goes. I'll post up the results here.

\$\endgroup\$
  • \$\begingroup\$ The very first LCD module I ever got, circa 1989, was DOA; the enable line acted like a 100-ohm or so resistor to ground. Digi-Key replaced it at no charge other than shipping (nice of them) and the replacement worked first try. \$\endgroup\$ – supercat Apr 19 '11 at 18:08
  • \$\begingroup\$ I don't think the LCDs are damaged. Tech support corrected themselves and let me know that the blocks will not appear when the contrast pot is adjusted w/o initializing first. Still working on this! \$\endgroup\$ – Dave Apr 22 '11 at 14:56
0
\$\begingroup\$

Could it be possible that you have the pins wired in reverse?

Every once in a while, I would come across LCD's with the pin numbers reversed either on the part itself or on the datasheet or both.

I know this might seem like an "is it plugged in?" question - but I've personally been caught by surprise with this.

* EDIT *

Ugh, in my earlier comment, I said to write 0x80 -- what I intended was for you to try and holding the value 0x40 or 0x60 to the data lines.

If it turns out the pins are reversed, writing 0x40 would apply power and ground via the data pins to the LCD, giving it a chance to do its self-reset. This is possible because a typical character LCD module only draws like 1 to 5 mA of current, well within the driving ability of most outputs.

What I suspect may be happening is that you are writing some 0x6X and 0x4X values to your LCD for a brief period of time while you're initializing the LCD -- and that the LCD is powering up during that brief period; but when you start writing other values, you are effectively turning it off.

* EDIT 2 *

While looking up the datasheet of another LCD to verify the current requirements, I noticed that you may have your Vcc and Vcontrast pins swapped. Make sure you check that as well!

I just looked and saw in the NHT-C0220AZ-FWS-FTW datasheet (where you got your schematic drawing above) that the contrast is pin 2, and supply voltage is pin 3. Which is the reverse of the Vishay and Optrex parts where contrast is pin 3, and supply voltage is pin 2.

Well, heck, even NewHaven's NHD-0420DZ-FSW-FBW has contrast on pin 3 and supply on pin 2.

\$\endgroup\$
  • \$\begingroup\$ Well, I went straight off of their datasheet, rather than pulling from past experience, so I am all wired up properly. But what it sounds like, tech support thinks I simply shouldn't use this LCD with the MSP430 due to incompatible voltage levels. I have a 3.3V part on order and that might solve all of my problems. But honestly, I still don't understand why a 3.3V MCU wouldn't work with this LCD. \$\endgroup\$ – Dave Apr 24 '11 at 3:28
  • \$\begingroup\$ In reference to your first edit, I don't believe this is the case. I've got the LCD powered up long before I go through my initialization routine. \$\endgroup\$ – Dave Apr 24 '11 at 3:29
  • \$\begingroup\$ Looking at the datasheet on your specific part, I agree that it looks like it would be able to operate (although at the margins) at 3.3V. \$\endgroup\$ – Toybuilder Apr 25 '11 at 6:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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