This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

help with 16x2 LCD

I am using a 16x2 LCD.. (1602ZFA)

I have used Port B of the Tiva C Launchpad as the data bus for the 8-bit LCD..

The connections are as follows :-

Board Pins = PB0   PB1   PB2   PB3   PB4   PB5   PB6   PB7   PA6   PA7

LCD Pins    = D0     D1     D2     D3     D4     D5      D6      D7     RS     EN

The RW pin has been connected to the ground.. I have turned ON the LCD's backlight and have used a POT on Vo pin.. Also, I am using the board at 40MHz system frequency.. The code is as follows :-

#include <stdint.h>

#include <stdbool.h>

#include "inc/hw_types.h"

#include "inc/hw_memmap.h"

#include "driverlib/sysctl.h"

#include "driverlib/gpio.h"

int main(void)

{

uint8_t ui8Value[]={0x38, 0x0e, 0x01, 0x06, 0x80};

uint8_t value;

//------------------- Tiva C Launchpad System Initilization------------------//

SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL| SYSCTL_XTAL_16MHZ|

SYSCTL_OSC_MAIN);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);

GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_2 | GPIO_PIN_3|GPIO_PIN_4 | GPIO_PIN_5| GPIO_PIN_6 | GPIO_PIN_7);

//------------------End of Tiva C Launchpad System Initilization------------//

SysCtlDelay(13333);

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x00);

for(value=0;value<=4;value++)

{

//-------------------------------LCD Command----------------------------//

//Put on the Data Pins 0x38 to get 2 Lines 5x7 Matrix (D0-D7, 8Bit)//

GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_2 | GPIO_PIN_3

|GPIO_PIN_4 | GPIO_PIN_5| GPIO_PIN_6 | GPIO_PIN_7, ui8Value[value]);

//Register Select(RS) = 0, Enable(E) = 1//

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x80);

//Enable Pulse Width (High Level) 1 millisecond//

SysCtlDelay(13);

//Register Select(RS) = 0, Enable(E) = 0//

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x00);

//---------------------------End of LCD Command------------------------//

SysCtlDelay(13333);

}

//---------------------------LCD Data Write--------------------------//

GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_2 | GPIO_PIN_3

|GPIO_PIN_4 | GPIO_PIN_5| GPIO_PIN_6 | GPIO_PIN_7, 0x42);

//Register Select(RS) = 1, Enable(E) = 1//

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0xC0);

//Enable Pulse Width (High Level) 1 millisecond//

SysCtlDelay(13);

//Register Select(RS) = 1, Enable(E) = 0//

GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x40);

SysCtlDelay(8333);

//--------------------------- End of LCD Data Write-------------------------//

while(1)

{

}

}

The problem is that as soon as I run the code, all the matrices of the first and second row become dotted and nothing else happens.. How should I modify the code so that it runs perfectly..

(For the enable signal, I am using a 1 millisecond high pulse)

  • Do you by any chance have a logic analyzer or oscilloscope? The first thing I would check is the actual timing on the bus. It seems the LCD isn't getting the data you think you're sending. Often a quick poke with the scope helps me to debug the software side of things.

  • Perseverance and (some) attention to the spec - I'd say...

    Have you the HD44780 or clone spec?  As I recall - you need "set-up & hold" times for both your data bus and RS + R/W, prior to the assertion of strobed E.   Code you show fails badly - those areas. 

    a) Your "Lcd Data Write" code sequence reveals both RS & E toggling together (via 0x0C) which is a clear, 44780 spec violation.  You must toggle RS alone - allow set-up time to pass - and only then assert the E strobe.  Subsequent calls to that function should work - as RS has already been set - but the initial "combined" toggle of RS & E will surely fail.

    b) When you view a darkened pixel field - it may indicate too high a contrast setting.  Lighten the pixel field - via your contrast pot - after you've initialized.  Often this helps. 

    You appear very close - give these code "mods" a try & kindly report...

     

  • @Alexander : No, I don't have an oscillioscope or any other scope.

    @cb1_mobile : Yeah I tried lightening the pixel field but that didn't help.. And, how much delay should I insert between RS and E signal? Also, what should be the setup and hold times for the data bus and RS+RW?

    And I have also modified my code a bit, as directed by cb1_mobile as follows :-

    /* PA6 - RS */

    /* PA7 - EN */

    #include <stdint.h>

    #include <stdbool.h>

    #include "inc/hw_types.h"

    #include "inc/hw_memmap.h"

    #include "driverlib/sysctl.h"

    #include "driverlib/gpio.h"

    int main(void)

    {

    uint8_t ui8Value[]={0x38, 0x0e, 0x01, 0x06, 0x80};

    uint8_t value;

    //------------------- Tiva C Launchpad System Initialisation------------------//

    SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL| SYSCTL_XTAL_16MHZ|

    SYSCTL_OSC_MAIN);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);

    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_2 | GPIO_PIN_3|GPIO_PIN_4 | GPIO_PIN_5| GPIO_PIN_6 | GPIO_PIN_7);

    //------------------End of Tiva C Launchpad System Initialisation------------//

    /* Wait 1 Millisecond after LCD Power Up */

    SysCtlDelay(13333);

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x00);

    for(value=0;value<=4;value++)

    {

    //-------------------------------LCD Command----------------------------//

    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_2 | GPIO_PIN_3

    |GPIO_PIN_4 | GPIO_PIN_5| GPIO_PIN_6 | GPIO_PIN_7, ui8Value[value]);

    /* Register Select(RS) = 0 for 200ns */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, 0x00);

    SysCtlDelay(3);

    /* Enable Pulse Width (High Level) 1us */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0x80);

    SysCtlDelay(13);

    /* Register Select(RS) = 0, Enable(E) = 0 for 100ns */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x00);

    SysCtlDelay(2);

    /* Setting up RS and EN again */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6|GPIO_PIN_7, 0x40);

    SysCtlDelay(2); /* 100ns */

    //---------------------------End of LCD Command------------------------//

    /* 1 milliseconds delay */

    SysCtlDelay(13333);

    }

    //---------------------------LCD Data Write--------------------------//

    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_2 | GPIO_PIN_3

    |GPIO_PIN_4 | GPIO_PIN_5| GPIO_PIN_6 | GPIO_PIN_7, 0x41);

    /* Register Select(RS) = 1 for 200ns */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, 0x40);

    SysCtlDelay(3);

    /* Enable Pulse Width (High Level) 1us */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0x80);

    SysCtlDelay(13);

    /* Register Select(RS) = 1, Enable(E) = 0 for 100ns */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x40);

    SysCtlDelay(2);

    /* Setting up RS and EN again */

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6|GPIO_PIN_7, 0x00);

    SysCtlDelay(2); /* 100ns */

    //--------------------------- End of LCD Data Write-------------------------//

    while(1)

    {

    }

    }

    But again I am facing the same issue..

    I checked the data appearing on the LCD data pins using my common-anode type Seven segment display.. So I connected the COM pin of 7-segment to 3V3 and then connected the "a" segment one by one to the 8 data pins using a resistor in between.. To my surprise, the "a" segment lit up on connection to all the data pins .. That means, 0x00 is appearing on the data pins which is not even mentioned anywhere in my code except for the RS and EN signals in the COMMANDS section..

  • Hey, the LCD is finally working with this code..

    Now just one thing's left.. The display is not able to clear itself even though I have given the command for it (0x01).. every time I write a new data, some garbage value also appears on the screen..

    Any suggestions??

  • Hi,

    As far as I remember from my use with such displays, the delays should be even bigger, something near 40 us - try first to increase the delays and then take a second approach: unused characters, if less than 16, should be filled up with spaces (0x20) so take care how do you do that.

    Petrei

  • sorry but I am not able to understand!!

    what do you mean by unused characters?

    I don't know that in which format the LCD is operating but sometimes it shows garbage values.. when I use 0x41 for "A", the LCD shows "C".. When I type in 0x42, the lcd shows "B".. for 0x43, it again shows "C".. for 0x44, it shows "F" which is actually the code for "D"..    Its confusing..

  • Good that you complied w/display's spec - making toggle of RS & E separate & independent.  (Yes - that does require separate instructions for RS & E - but only when RS is changing its logic level.) 

    To further clarify - during a display command write - clear RS - provide spec'ed delay - then pulse E from low to high back to low.  For an immediately following such display command - there is no need to attend to RS as it is already cleared to zero - thus no RS set-up time violation can occur.  (Clear?)

    During a data write - just post any display command - RS must be toggled from low to high.  And then - after waiting for the spec's required RS set-time - E is pulsed from low to high back to low.  (this is so as RS must change - making you again vulnerable to RS vs. E's set-up time spec)

    Your description of incorrect data does not seem consistent - 0x41 applied to the D-Bus - with RS=1 - and then the positive, proper strobe of E - should always yield "A" upon the display.  Your report of the display of "C" (0x43) may suggest that your data bit D1 is "stuck" high - or may be shorted to adjacent data line D0!   Your report of 0x01 "failing to {CLS} clear the screen" - offers further support for the diagnosis of a D0-D1 short!!  (why I get "big bucks")

    Your use of a single segment of a 7 Segment Led as a test device is inventive but we past employed a linear array of 08-05 smt Leds.  First 8 (in a row) were labeled D0-D7 - and monitored the D-Bus.  And we had 3 more to reflect (actually illuminate) the logic state of RS, RW & E.  We built this as a production item - and always designed our prototypes so this simple piece of "test gear" could quickly/easily just, "plug-in" to a standard header. 

    Your time (and morale) is of some importance - probing one pin @ a time "eats time/effort/comfort!"  (and a "slip" may cause circuit/component damage!)  Alternative suggested here connects positively/correctly just once - provides a clear graphic-like readout of all critical signals - avoids circuit/component damage - and may be quickly/inexpensively constructed. 

  • yeah..

    As far as the strobing of RS and E pins is concerned, I think I have taken care of the that in the code that I had mentioned above.. (Correct me if I am wrong)

    And I would be checking up on the "D0-D1" short and will report here at the earliest..

    Thanks for the suggestions :)

  • This reporter has designed/produced & sold enough of these character Lcd modules - should be able to resolve this simple issue.   Here's what you report:  (note that I've made time/effort to better organize/present)

    MCU output:      Display shows...

    A   0x41              C  0x43  Error, 2 bits over

    B   0x42              B  0x42  Correct

    C  0x43               C  0x43  Correct

    D  0x44               F  0x46  Error, 2 bits over (again)

    Of course - more data would speed/ease this analysis.  Yet - from this limited data set - it seems safe to conclude that bit D1 (value =2) is indeed, "stuck high."

    Here's the justification: 0x41 does not order bit D1 high - thus should D1 be "stuck" high - your 0x41 + bit D1 = 0x43.

    Next, 0x42 does order bit D1 high - and as it's "stuck" high - no harm,  no foul.  This displays correctly.

    Onto 0x43 - now this again sets bit D1 (and bit D0) high - and displays C correctly.  D1 stuck high has no impact.

    And finally 0x44 - does not order bit D1 high - your stuck D1 does that nicely - and voila 0x44 + bit D1 = 0x46 = F.

    Q.E.D.  (one final weasel/hedge - HD44780 & most clones pull-up their D-Bus.  Thus - your "stuck" bit may be evidence of an "open" circuit between MCU's D1 & Lcd's D1.) 

    The effect remains the same - the cure though is different!  Far easier to imagine your shorting bit D1 to D0 or D2 - how you short it to 3V3 - bit harder.  Thus - I lean to an "open" between your MCU->Lcd's D1 - preventing the MCU from overcoming the "weak pull up" resident w/in the Lcd controller... 

    Last Mohican point(s) - Petrei correctly recalled ~40uS as character to character delay.  But use a safety factor - 2x seems reasonable.  And the CLS command (0x01) and Home (0x02) may require a bit over 1mS!  (use 2mS)  It's good form to have 0x01 as the final entry w/in your Lcd initialization listing.  (yours appeared earlier)

    A nice, Verify answer tick seems proper/fitting & should close this topic.  (cards/letters/applause also welcome)