Microcontroller interfacing with LCD 16x1

Thread Starter

IamNew

Joined Dec 7, 2011
3
I am doing a microcontroller project which utilizing AT 89S52 and a LCD 16x1. I have problem when trying to display letter of 'N' to the LCD. I could have the display on the LCD display but it only give me the LCD backlight and show me the black boxes. My microcontroller is tested fine.

Below is the codes that I programmed into my microcontroller
Rich (BB code):
//Program to test LCD. Display single character "A"

#include<reg51.h>
#define cmdport P3
#define dataport P2
#define q 100
sbit rs = cmdport^0;  //register select pin
sbit rw = cmdport^1;  // read write pin
sbit e = cmdport^6;  //enable pin

void delay(unsigned int msec)  // Function to provide time delay in msec.
{
int i,j ;
for(i=0;i<msec;i++)
for(j=0;j<1275;j++);
}

void lcdcmd(unsigned char item)  //Function to send command to LCD
{
dataport = item;
rs= 0;
rw=0;
e=1;
delay(1);
e=0;
}

void lcddata(unsigned char item)  //Function to send data to LCD
{
dataport = item;
rs= 1;
rw=0;
e=1;
delay(1);
e=0;
}

void main()
{
lcdcmd(0x38);  // for using 8-bit 2 row mode of LCD
delay(100);
lcdcmd(0x0E);  // turn display ON for cursor blinking
delay(100);
lcdcmd(0x01);  //clear screen
delay(100);
lcdcmd(0x06);  //display ON
delay(100);
lcdcmd(0x86);  // bring cursor to position 6 of line 1
delay(100);
lcddata('A');
}

Below is schematic of my circuit:



Please guide me if I am wrong somewhere in the circuit or the code.
 

T.Jackson

Joined Nov 22, 2011
328
Sure. I will appreciate it very much.
Well, I could tell almost straight away that you don't have many flight hours as a general programmer. I think you're starting off with too high of expectations, trying to bite off a bit more than you can chew without having a solid grip on general problem solving.

This is not easy to learn by yourself, and you could be in for many, many years of it without doing some form of formal study.

You can do some online courses with computer programming, not necessarily for MCUs like PIC and Atmel, but perhaps Java programming, which is 100% relevant to what you're trying to do right here now. the C syntax is the same as Java, and any skills that you acquire whilst learning Java you will be able to carry across with you to other languages.

I don't see valid algorithms in your code. If you cannot do this, then it is just just too hard, short of having an IQ of like 150 or more you will spend years trying to come to grips with it without getting some formal help.
 

Georacer

Joined Nov 25, 2009
5,181
T.Jackson, I remind you that this is a site focused on education and hobbyists. You are not to expect full professionalism and mastery of the topic at hand on everyday basis.

You are welcome to give any helpful and constructive input in order to help the inquirer towards his goal, given that it is achievable and feasible. Keep, however, in mind that the user might not be after complete mastery of the subject, but just wants to make his contraption work. We are not the ones to tell him that he has to get a degree first. If you don't have anything to add towards that direction, you can choose not to answer in his thread.

Education is always welcome, but let's be reasonable about it.
 

AlexR

Joined Jan 16, 2008
732
The LCD initialisation sequence in your source code does not look right.
The LCD display initialisation sequence is quite involved and must be done as per the data sheet for the controller that the display uses.
If you know which control chip your display uses get its data sheet and follow the recommended initialisation sequence to the letter, paying careful attention to include all the recommender delays.
The HD44780 is one of the most common controller in use so if you don't know your controller type try using the initialisation sequence on pages 45 (8 bit mode) and 46 (4 bit mode) of the HD44780 Data Sheet
 

MrChips

Joined Oct 2, 2009
19,930
I am doing a microcontroller project which utilizing AT 89S52 and a LCD 16x1. I have problem when trying to display letter of 'N' to the LCD. I could have the display on the LCD display but it only give me the LCD backlight and show me the black boxes. My microcontroller is tested fine.

Are you saying that it displays all other characters besides 'N' correctly?
 

spinnaker

Joined Oct 29, 2009
7,837
Please guide me if I am wrong somewhere in the circuit or the code.
The very first thing I would do is to write a little test program to toggle each bit going to the LCD and put a logic or scope probe on each LCD connection to make absolutely sure you have everything connected the way you think they should be connected.


As someone said above your init code looks way to simple.

Here is some code for LCD. It is for the PIC but you should be able to translate it fairly easily. One thing to know that the delays you use between commands and data are very important that they are set to the correct length.

Rich (BB code):
#define LCD_RS            LATCbits.LATC5        // Control (1=Command 0=Data)
#define LCD_RS_TRIS        TRISCbits.TRISC5    // LCD Control TRIS

#define LCD_E            LATCbits.LATC4           // Enable pin
#define LCD_E_TRIS        TRISCbits.TRISC4    // LCD Enable TRIS
#define LCD_E_ANS        ANSELbits.ANS3

#define LCD_DB7         LATBbits.LATB7        // LCD Data Bit 7
#define LCD_DB7_TRIS    TRISBbits.TRISB7    //LCD Data Bit 7 TRIS

#define LCD_DB6         LATCbits.LATC7        // LCD Data Bit 6
#define LCD_DB6_TRIS     TRISCbits.TRISC7    //LCD Data Bit 6 TRIS
#define    LCD_DB6_ANS        ANSELHbits.ANS9

#define LCD_DB5         LATCbits.LATC6        // LCD Data Bit 5
#define LCD_DB5_TRIS     TRISCbits.TRISC6    //LCD Data Bit 5 TRIS
#define LCD_DB5_ANS        ANSELHbits.ANS8

#define LCD_DB4         LATCbits.LATC3        // LCD Data Bit 4
#define LCD_DB4_TRIS    TRISCbits.TRISC3    //LCD Data Bit 4 TRIS
#define LCD_DB4_ANS        ANSELbits.ANS7


/*

#define LCD_RS            LATBbits.LATB7        // Control (1=Command 0=Data)
#define LCD_RS_TRIS        TRISBbits.TRISB7    // LCD Control TRIS

#define LCD_E            LATCbits.LATC7           // Enable pin
#define LCD_E_TRIS        TRISCbits.TRISC7    // LCD Enable TRIS
#define LCD_E_ANS        ANSELHbits.ANS9

#define LCD_DB7         LATCbits.LATC5        // LCD Data Bit 7
#define LCD_DB7_TRIS    TRISCbits.TRISC5    //LCD Data Bit 7 TRIS

#define LCD_DB6         LATCbits.LATC4        // LCD Data Bit 6
#define LCD_DB6_TRIS     TRISCbits.TRISC4    //LCD Data Bit 6 TRIS


#define LCD_DB5         LATCbits.LATC3        // LCD Data Bit 5
#define LCD_DB5_TRIS    TRISCbits.TRISC3    //LCD Data Bit 5 TRIS
#define LCD_DB5_ANS        ANSELbits.ANS7

#define LCD_DB4         LATCbits.LATC6        // LCD Data Bit 4
#define LCD_DB4_TRIS    TRISCbits.TRISC6    //LCD Data Bit 4 TRIS
#define LCD_DB4_ANS        ANSELHbits.ANS8

*/

void LCD_nybble(unsigned char data,char rs);
void LCD_e_togg (void);


void LCD_Init(void)
{

    LCD_RS_TRIS = 0;
    LCD_E_TRIS = 0;
    LCD_DB7_TRIS = 0;
    LCD_DB6_TRIS = 0;
    LCD_DB5_TRIS = 0;
    LCD_DB4_TRIS = 0;
    
    LCD_E_ANS = 0;    
    LCD_DB4_ANS = 0;
    LCD_DB4_ANS = 0;
/*
    while (1)
    {

    LCD_RS = 0;
    LCD_E = 0;
    LCD_DB4 = 0;
    LCD_DB5 = 0;
    LCD_DB6 = 0;
    LCD_DB7 = 0;


    delay_ms(10);

    LCD_RS = 1;
    LCD_E = 1;
    LCD_DB4 = 1;
    LCD_DB5 = 1;
    LCD_DB6 = 1;
    LCD_DB7 = 1;

    delay_ms(10);
}

*/    

    //This is our lcd initialization function
    delay_ms(20);                   // Wait at least 16 mS after powerup

    LCD_nybble(0x03,0);             //send 0x03 cmd 3 times to initialize
    delay_ms(5);

    LCD_e_togg();                   //Since 0x03 nybble is on the port already
    delay_us(160);                  // we just toggle 2 more times

    LCD_e_togg();
    delay_us(160);

    LCD_nybble(0x02,0);             //Enable 4 bit mode
    delay_ms(1);

    LCD_cmd(0b00101100);            //set 4-bit mode and 2 lines @ 5x7
    delay_us(160);

    LCD_cmd(0x10);                    //cursor move & shift left
    delay_us(160);

    LCD_cmd(0x06);                    //entry mode = increment
    delay_us(160);

    LCD_cmd(0b0001100);                //display on - cursor blink off
    delay_us(160);

    LCD_cmd(0x01);                    //clear display
    delay_us(160);

    delay_ms(5);
}

void LCD_e_togg (void)
{
//This is our toggle E line function to 
//tell lcd to accept data
    LCD_E=1;     
    LCD_E=0;
     
}

void LCD_cmd(unsigned char letter)
{
//This is our Command Function
//The RS is set to 0 to signify this is a command
    unsigned char temp;             //Our temp Variable

    temp=letter;                    //move letter to temp
    temp=temp>>4;                   //shift temp to right by 4
    LCD_nybble(temp,0);             //send the 4 out

    temp=letter;                    //move letter to temp
    temp=temp&0x0f;                 //and out first 4
    LCD_nybble(temp,0);             //send out last 4

    delay_us(10);
}

void LCD_char(unsigned char letter)
{
//This is the same as the lcd_cmd function except
//that is sets RS to 1 telling the lcd this is characters
    unsigned char temp;

    temp=letter;
    temp=temp>>4;
    LCD_nybble(temp,1);

    temp=letter;
    temp=temp&0x0f;
    LCD_nybble(temp,1);
}

void LCD_string(char *senpoint, char Line)
{
    if(Line == 1)
        LCD_cmd(LINE1);
    else
        LCD_cmd(LINE2);

    while(*senpoint != '\0')            // While we havent seen a \0 (esc) go on
    {
        LCD_char(*senpoint);            // Send 1st char to our char function
        senpoint++;                     // Send next
    }

    delay_us(10);
}
void LCD_nybble(unsigned char nyb,char rs)
{
    char i;
    char x;

    LCD_RS = rs;                    // Set RS Pin (defined in header file)

    for(i=0;i<4;i++){                // Loop through nybble

        if((nyb & 0x08) != 0)       // AND the nybble to 8
            x=1;                    // If the AND == 1 set x
        else
            x=0;                    // If the AND == 0 clear x

        if(i==0)                    // Select RA3:RA0 and set or clear pins
            LCD_DB7=x;

        if(i==1)
            LCD_DB6=x;

        if(i==2)
            LCD_DB5=x;

        if(i==3)
            LCD_DB4=x;


        nyb=nyb<<1;                 // Shift nybble to the left by 1 (4 times total)
    }

    LCD_e_togg();                   // Toggle E pin (defined in header file)
}

void LCD_clr_line(char line)
{
//This is our clear line command.
    char tline;                             // The line to clear variable
    char x;                                 // loop variable

    if(line==0)                             // Set the variable value based on line
        tline=0x80;                         // 0 = Line 1
    else
        tline=0xA8;                         // 1 = Line 2

    LCD_cmd(tline);                         // Send command to jump to beggining of line (1/2)
    delay_ms(1);

    for(x=0;x<40;x++){                      // Loop through all 40 chars of line (even tho 16 are viewable)
        LCD_char(0x20);                     // Send Blank Character
        delay_us(50);                  
    }

    LCD_cmd(tline);                         // Go back to beggining of line
    delay_ms(1);
}
 

THE_RB

Joined Feb 11, 2008
5,438
I don't think the code looks "too simple" it has everything needed, a function to send a command byte, a char byte and an init function.

It's a good idea to REALLY double check the pins you use for RS E and RW, and also the data lines. Check the IC pins match the port pins as declared in your code.

And check your init function, it's a good idea to send the top command 3 times, like in the datasheet recommended procedure (that AlexR suggested above).

And always check your contrast pot and contract pin voltage! I've been caught out in the past chasing software when it was as simple as me forgetting to set the contrast pot, and immediately assuming it was software or bad pin wiring. ;)
 
Top