loading

LCD & PIC18F4520!

I am trying to write HELLO on an LCD. It is a 16x1 (called WH1601A). I am using C18 language with ICD3. My 8 data lines are connected to PORTD[0-7]. My 3 control lines are connected to PORTB[0-2]. I can see 8 shaded boxes on my LCD which occupies half of the screen, but when i run the program nothing happens and the 8 boxes just stay there and nothing is written. I have been going at this for 2 days to no avail. I'm guessing the mistake is from the code, please take a look! Help will be much appreciated.


#include <p18F4520.h>

#pragma config WDT = OFF

//DEFINING PORTS
#define rs PORTBbits.RB0
#define rw PORTBbits.RB1
#define en PORTBbits.RB2
#define data PORTD

//Function prototypes
void init(void);
void LCD_init(void);
void LCD_data(unsigned char);
void LCD_cmd(unsigned char);
void LCD_busy(unsigned int);
void LCD_sendstring(unsigned char *var);

void main()
{
init();
LCD_init();
LCD_sendstring("Hello");
while(1);
}

void LCD_sendstring(unsigned char *var)
{
     while(*var)              //till string ends
       LCD_data(*var++);  //send characters one by one
}

//Initialize the LCD
void LCD_init()
{
LCD_cmd(0x01);     //Clear LCD    
LCD_cmd(0x38);     //Function set: 2 Line, 8-bit, 5x7 dots  
//LCD_cmd(0x0C); // 1 line, 8 bit, 5x7;      
    LCD_cmd(0x0F);     //Display on, Curson blinking command             
    LCD_cmd(0x06);     //Entry mode, auto increment with no shift   
}

void LCD_data(unsigned char var)
{
     data = var;      //Function set: 2 Line, 8-bit, 5x7 dots
     rs   = 1;        //Selected data register
     rw   = 0;        //We are writing
     en   = 1;        //Enable H->L
  LCD_busy(1);
     en   = 0;
     LCD_busy(15);          //Wait for LCD to process the command
}
void LCD_cmd(unsigned char var)
{
     data = var;      //Function set: 2 Line, 8-bit, 5x7 dots
     rs   = 0;        //Selected command register
     rw   = 0;        //We are writing in instruction register
     en   = 1;        //Enable H->L
  LCD_busy(1);
     en   = 0;
     LCD_busy(15);          //Wait for LCD to process the command
}

void LCD_busy(unsigned int itime)
{
         unsigned char i,j;
         for(i=0;i<itime;i++)        //A simple for loop for delay
            for(j=0;j<255;j++);
}

void init()
{
OSCCONbits.IRCF2=1; //oscillator frequency = 8mhz
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF0=1;
ADCON1=0xFF; //make ports digital
TRISD=0x00; //PORTD output
TRISB=0x00; //PORTB output
PORTD=0x00;
PORTB=0x00;
en = 0;
LCD_busy(250);

}

Any idea guys?! This is the first time i work an LCD and I could not find a problem in the forums. 

sort by: active | newest | oldest
Chris414 (author) 4 years ago
Ok so all is good now! Here is my code if anyone ever needs it: MSDelay can be reduced to 1 instead of 15 to make the string just appear altogether instead of letter by letter.

#include
#include

//Config Bits
#pragma config WDT = OFF
#pragma config MCLRE = ON // MCLEAR Pin on
#pragma config DEBUG = ON // Enable Debug Mode
#pragma config LVP = OFF // Low-Voltage programming disabled
#pragma config OSC = INTIO67 //Internal oscillator
#pragma config PWRT = OFF

//Function Prototypes
void lcdcmd(unsigned char value);
void lcddata(unsigned char value);
void MSDelay(unsigned int time);
void init();

//Port connections to PIC18F4520
#define rs PORTBbits.RB0
#define rw PORTBbits.RB1
#define en PORTBbits.RB2
#define port PORTD

char a;
char b[]={" 5% GAS LEFT!!!"}; //INSERT A STRING HERE TO DISPLAY

//MAIN PROGRAM
void main(){

init();
TRISD = 0x00; //MAKE PORTS OUTPUTS
TRISB = 0x00;
PORTD = 0x00;
PORTB = 0x00;
en = 0;
MSDelay(250); //GIVE TIME FOR LCD TO WAKE UP


//LCD INITIALIZE. Use KS0066U datasheet page 26
lcdcmd(0x01);
MSDelay(15);
lcdcmd(0x06);
MSDelay(15);
lcdcmd(0x38);
MSDelay(15);
lcdcmd(0x0C);
MSDelay(15);

//THIS IS THE SEND STRING PART TURN TO FUNCTION!!!
if (strlen(b)>8)
{
//write first 8 characters
for(a=0;a<8;a++){
lcddata(b[a]);
MSDelay(15);
}
//The 2 lines are necessary to make all 16 characters appear not //only 8! It sends cursor to DDRAM location 0x40

lcdcmd(0xC0);
MSDelay(15);
//write characters 9-16
for(a=8;a lcddata(b[a]);
MSDelay(15);
}
//These for loops send the string character by character
}
else
{
//if the string is less than 8 characters just write it
for(a=0;a lcddata(b[a]);
MSDelay(15);
}
}
//END OF SEND STRING

while(1);
}

//lcd instructions
void lcdcmd(unsigned char value){
port = value;
rs = 0;
rw = 0;
en = 1;
MSDelay(1);
en = 0;
}

//lcd data
void lcddata(unsigned char value){
port = value;
rs = 1;
rw = 0;
en = 1;
MSDelay(1);
en = 0;
}

//Simple delay
void MSDelay(unsigned int itime){
unsigned int i, j;
for(i=0;i for(j=0;j<350;j++);
}

void init()
{
ADCON1=0xFF; //make ports digital!!
OSCCONbits.IRCF2=1; //oscillator frequency = 8mhz
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF0=1;
}
Chris414 (author) 4 years ago
ZOMGGGGGGGGGG I AM JUMPING FROM JOYYYYYY!!!!

It turns out one of the data pins was not soldered right on my board!!

BUT only 8 characters are appearing. These are my initialization bits.

lcdcmd(0x0C);
lcdcmd(0x01);
lcdcmd(0x06);
lcdcmd(0x80);

Any ideas?!
You have simply got the init wrong.

It SHOULD be

38,38,0C,0F, 06.

DO NOT do anything to the display after reset but the two 38s FIRST.
Chris414 (author)  steveastrouk4 years ago
Thank you very much Steve for your answer. So basically I changed the LCD_init() function to this:

void LCD_init()
{
LCD_cmd(0x38);
LCD_cmd(0x38);
LCD_cmd(0x0C);
LCD_cmd(0x0F);
LCD_cmd(0x06);
}

However, still nothing is happening. I am wondering about 2 things:
1- Should the delays be exactly a value?? Or should they be MORE than a certain value. I tried to increase the delay alot but still nothing works.
2- Should the LCD show signs that its trying to initialize or do something?Or if the initialization is not exactly correct, simply nothing will happen and the 8 black boxes will just stay there?With all the codes i've tried (ones i did and ones i got online), the lcd simply stay there, it has never shown me signs of life.(other than the 8 black boxes). Is there maybe something wrong with it?

Again thank you very much!
If the initialisation works, the display becomes noticeably "dimmer"
Timings can be longer, but not shorter.
The first two commands take longer than the rest - 5ms.
Have you got a contrast pot on it ???

Try 30H, 30H for the first two initialisations.

Without an oscilloscope, you are blind. Since you are working on a 5V system, you could do worse than find "WinScope", which uses a windows sound card as an oscilloscope up to high audio frequencies.

Yes, if the initialisation fails, the black boxes stay

You have initialised a TWO line display, but you only have ONE.

Its a long time since I last wrote the code. Here's a useful link I just found
http://web.alfredstate.edu/weimandn/lcd/lcd_initialization/lcd_initialization_index.html

Timing can be longer, but not shorter than the limits, and the first two instructions take several MILLIseconds to complete.

You should try 30H 30H for the first two initialisations.