Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Integrating LCD with pic18f452

Status
Not open for further replies.

smurf.

New Member
Hello!

I'm working on a major project, and I'm having trouble integrating an LCD module with the pic18f452. I'm using MPLAB IDE v8.87, c18 compiler. My LCD just shows a black line! So any help would be much appreciated!

Here's some info about the hardware:
I'm using a PICDEM2+ board (green) but the LCD on it is broken, hence using an external one. The LCD uses a KS0066U controller, but I know it's basically the same as a HD44780 controller.

The connections are as follows:
Pins D4-D7 - D0-D3
E - RA1
RW - RA2
RS - RA3
Vee - I'm using a voltage divider which gives a voltage of approx. 1V (someone stole my trimpot)

The code is as follows:
Code:
#include <p18f452.h>
#include <delays.h>

#define EN 		PORTAbits.RA1    // Assigning RA1 for Enable on LCD controller
#define RW 		PORTAbits.RA2    // Assigning RA2 for Write on LCD controller
#define RS 		PORTAbits.RA3    // Assigning RA3 for Register Select on LCD
//#define PORTD  	LATD

#define line1_pos 0x80	
#define line2_pos 0xC0

// Writes command in 4-bit mode to LCD
void lcd_cmd(unsigned char c){
	
	unsigned char temp;
	
	EN = 0;
	RS = 0;
	RW = 0;

	temp = c;
	temp = temp >> 4;
	temp = temp & 0x0F;			//clear top bits of dat
    PORTD = PORTD & 0xF0;		//clear bottom bits of port (interested only in DB7-DB4)
    PORTD = PORTD | temp;
    
    EN = 1;
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    							//Total is approximately 450ns
    EN = 0;
    
    Delay1KTCYx(20);				//Delay for 5ms = 20,000 Tcy for command writes
    
	temp = c;
	temp = temp & 0x0F;			//clear top bits of dat
    PORTD = PORTD & 0xF0;		//clear bottom bits of port (interested only in DB7-DB4)
    PORTD = PORTD | temp;
    
	EN = 1;
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
        						//Total is approximately 450ns
    EN = 0;
    
    Delay1KTCYx(20);				//Delay for 5ms = 20,000 Tcy for command writes
    
}


// Write character data in 4-bit data to LCD
void lcd_data(unsigned char c){
	
	unsigned char temp;
	
	EN = 0;
	RS = 1;
	RW = 0;

	temp = c;
	temp = temp >> 4;
	temp = temp & 0x0F;			//clear top bits of dat
    PORTD = PORTD & 0xF0;		//clear bottom bits of port (interested only in DB7-DB4)
    PORTD = PORTD | temp;
    
    EN = 1;
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    EN = 0;
    
    Delay100TCYx(8);				//Delay for 200us = 800 Tcy for data writes
    
	temp = c;
	temp = temp & 0x0F;			//clear top bits of dat
    PORTD = PORTD & 0xF0;		//clear bottom bits of port (interested only in DB7-DB4)
    PORTD = PORTD | temp;
    
	EN = 1;
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    Delay1TCY()					//Delay of exactly 1 Tcy = 0.25us
    EN = 0;
    
    Delay100TCYx(8);				//Delay for 200us = 800 Tcy for data writes

}


// Clears LCD display
void lcd_clear(void){
	lcd_cmd(0x01);
	Delay1KTCYx(5);	//5ms
}


//Writes nibble to PORTD
void lcd_nibble(unsigned char nib){
	
	unsigned char temp;
	
	temp = nib;
	temp = temp & 0x0F;			//clear top bits of dat
    PORTD = PORTD & 0xF0;		//clear bottom bits of port (interested only in DB7-DB4)
    PORTD = PORTD | temp;
    	
} 


//Initialise the LCD
void lcd_init(void){
	
	Delay1KTCYx(120);				//Wait for 30ms = 120,000 Tcy for LCD to power up

	// Set up LCD interface to 4-bit mode, 2 lines, 5*10 dots
	lcd_cmd(0x28);
	Delay100TCYx(2);				//Delay for ~40us = 160 Tcy
	
	// Enable display/cursor - cursor moves right, display is not shifted
	lcd_cmd(0x08);
	Delay100TCYx(2);				//Delay for ~40us = 160 Tcy
	
	// Clear display
	lcd_cmd(0x01);
	Delay1KTCYx(7);					//Delay for ~1.53ms = 6120 Tcy
	
	// Set cursor move direction
	lcd_cmd(0x06);
	Delay100TCYx(2);				//Delay for ~40us = 160 Tcy

	// Turn on display
	lcd_cmd(0x0C);
	Delay100TCYx(2);				//Delay for ~40us = 160 Tcy	
	
}


// Write string to LCD
void lcd_write(const char *message){
	
	while(*message){
		lcd_data(*message++);
	}
}


// Select line
void lcd_line(unsigned char position){

	//Line 1
	if (position = 1){
		lcd_cmd(0x80);
	}

	//Line 2
	if (position = 2){
		lcd_cmd(0xC0);
	}
}

// Main code
void main(){

	TRISA = 0x00;
	TRISD = 0x00;

	EN = 0; 
	RS = 0;
	RW = 0;

	PORTA = 0x00;
	PORTD = 0x00;
	Delay1KTCYx(1);		// 1 ms delay
	lcd_init();

	while(1){
		lcd_line(1);
		lcd_write("Hello");
	}	
}
 
Last edited:
As It has one line in black squares.. We can rule out contrast... We are now looking at the init and command write routines.

PORTD = PORTD & 0xF0... is preserving the last data written, Just clear PORTD then OR the data in.... (This is if you are using the high byte of PORTD.. the text above the code is confusing me ).

Some compatibles do not work in 4 bit mode...
 
Code:
	if (position = 1){
This is valid c code, but does not do what you think it does.

Code:
	if (position == 1){
Double equals to check for equality within an if statement

Code:
#define EN 		PORTAbits.RA1    // Assigning RA1 for Enable on LCD controller
Usually you would use LAT registers for output, like this:

Code:
#define EN 		LATAbits.LATA1    // Assigning RA1 for Enable on LCD controller


also... Not strictly necessary for your code, but it is usual to disable analogue function on PORTA as described in the datasheet. Something like ADCON1 = 7;
 
Last edited:
Thank you Ian Rogers & hexreader for your advice!

My friend tried to fix up the code for me, and I took your advice into account, but it's still showing a black line :(

Would you happen to know where I can get working code? Or a tutorial that explains it step by step? I've gone through numerous tutorials and to no avail! I still fail at coding the LCD :(
 
An old - unfinished project attached. The project talks to LCD with control pins on PORTA and also talks on serial port at 9600,8,n,1. You should see LEDs count when the board first runs (assuming J6 link is in) and you should get serial port communication, even if your LCD is not compatible or not wired correctly (barring a short)

Uses 4MHz canned oscillator as supplied with PICDEM2 plus.

Note that there are two main versions of PICDEM2 plus. (and a few sub-versions) with the main difference being with the LCD control pins.

The older version, with 3 LCD control pins on PORTA - usually, but not always with a red PCB.

The newer version has 4 LCD control pins on PORTD - usually, but not always with a green PCB. This version has an extra control pin to turn the LCD power on and off.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top