LPC and LCD problem

Hello community !

I<m trying to interface a 4x20 LCD with an LPC-2468. I sill cannot see anything on the LCD.

here is the interfacing :

P0.4 → D4

P0.5 → D5

P0.6 → D6

P0.7 → D7

P4.15 → E

P4.27 → RS

P4.29 → RW

#include "lpc2468_registers.h"
#include "lcd.h"



#define BUSY_MASK       0x00000080

#define TRUE	1
#define	FALSE	0

void InitLeds(void);

void InitPLL(void);
void feed(void);

void IRQ_Routine (void)   __attribute__ ((interrupt("IRQ")));
void FIQ_Routine (void)   __attribute__ ((interrupt("FIQ")));
void SWI_Routine (void)   __attribute__ ((interrupt("SWI")));
void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF")));


/* return TRUE if the button is pressed */
int But1Pressed(void)
{
	if (FIO2PIN & (1<<13)) return FALSE;
	else return TRUE;
}
int But2Pressed(void)
{
	if (FIO2PIN & (1<<21)) return FALSE;
	else return TRUE;
}

void Delay(void)
{
	int j;
	for (j = 0; j < 10000; j++ );
}


void lcd_string(char *senpoint)
{
	while(*senpoint != '\0')
	{
		lcd_char(*senpoint);
		senpoint++;
	}
}	

void lcd_line1(void)
{
	lcd_cmd(0x80);
}

void lcd_line2(void)
{
	lcd_cmd(0xc0);
}		

void lcd_line3(void)
{
    lcd_cmd(0x94);
}       

void lcd_line4(void)
{
    lcd_cmd(0xd4);
}       

void lcd_cmd(unsigned char letter)
{
	unsigned char temp;
	temp=letter;
	temp=temp>>4;
	lcd_nybble(temp,0);
	temp=letter;
	temp=temp&0x0f;
	lcd_nybble(temp,0);
}

void lcd_char(unsigned char letter)
{
	unsigned char temp;
	temp=letter;
	temp=temp>>4;
	lcd_nybble(temp,1);
	temp=letter;
	temp=temp&0x0f;
	lcd_nybble(temp,1);
}

void lcd_nybble(unsigned char nyb,unsigned char rs)
{
	int i,dat;
	if(rs)
		FIO4SET |= 1<<27;				//set RS pin
	else
		FIO4CLR |= 1<<27;				//clear RS pin
	dat = nyb;						//get the nybble in an int
	
	FIO0CLR |= 1<<4; // D4
	FIO0CLR |= 1<<5; // D5
	FIO0CLR |= 1<<6; // D6
	FIO0CLR |= 1<<7; // D7

	FIO0SET |= dat<<4;				//OR the bits in there
	strobe_e();						//latch data to LCD
}

void lcd_init(void)
{
	delay_ms(500);					//settle time delay
	lcd_nybble(0x03,0);				//reset LCD
	lcd_nybble(0x03,0);
	lcd_nybble(0x03,0);
	delay_ms(5);
	strobe_e();
	delay_us(160);
	strobe_e();
	delay_us(160);
	lcd_nybble(0x02,0);
	delay_us(160);
	lcd_cmd(0x28);					//set 4-bit mode and 2 lines
	delay_us(160);
	lcd_cmd(0x10);					//cursor move & shift left
	delay_us(160);
	lcd_cmd(0x06);					//entry mode = increment
	delay_us(160);
	lcd_cmd(0x0e);					//display on - cursor blink on
	delay_us(160);
	lcd_cmd(0x01);					//clear display
	delay_ms(40);
}

void strobe_e(void)
{
	FIO4SET |= 1<<15;
	delay_us(1);
	FIO4CLR |= 1<<15;
	delay_us(160);
}

void delay_ms(int x)
{
	int a,b;
	for(a=0;a<x;a++){
		for(b=0;b<3500;b++);
	}
}

void delay_us(int x)
{
	int a,b;
	for(a=0;a<x;a++)
		for(b=0;b<4;b++);
}


/* return TRUE if the RTC is OK */
int TestRTC(void)
{
	int timeout = 1000000;
	RTC_CCR = 0;
	RTC_SEC = 0x00;
	RTC_CCR = 1<<1; /* clear the counter */
	RTC_CCR = 1<<0 | 1<<4; /* enable the clock using the external xtal */
	
	while (timeout--);
	timeout = RTC_CTC;
	
	if ((1550 < timeout) & (timeout < 1600)) return TRUE;
	
	return FALSE;
}



int	main (void) {
	
	int	j;										// loop counter (stack variable)
	//InitPLL();
	
	SCS |= 1<<0; /* enable fast IO on ports 0&1 */
	
	InitLeds();
	

	
		
	for (j = 0; j < 200000; j++);
	lcd_init();
	while(1){
		lcd_line1();
		lcd_string("LPC2148 LCD");
		delay_ms(1000);
		lcd_line2();
		lcd_string("It works!");
		lcd_line3();
		lcd_string("Line 3 here.");
		lcd_line4();
		lcd_string("Here is line 4!");
		delay_ms(1000);
	}

}


#define PLL_MValue	11
#define PLL_NValue	0
#define CCLKDivValue	4
#define USBCLKDivValue	5

void InitPLL(void)  
{

	volatile unsigned long MValue;
	volatile unsigned long NValue;

	if ( PLLSTAT & (1 << 25) )
	{
		PLLCON = 1;			/* Enable PLL, disconnected */
		PLLFEED = 0xaa;
		PLLFEED = 0x55;
	}

	PLLCON = 0;				/* Disable PLL, disconnected */
	PLLFEED = 0xaa;
	PLLFEED = 0x55;
    
	SCS |= 0x20;			/* Enable main OSC */
	while( !(SCS & 0x40) );	/* Wait until main OSC is usable */

	CLKSRCSEL = 0x1;		/* select main OSC, 12MHz, as the PLL clock source */

	PLLCFG = PLL_MValue | (PLL_NValue << 16);
	PLLFEED = 0xaa;
	PLLFEED = 0x55;
      
	PLLCON = 1;				/* Enable PLL, disconnected */
	PLLFEED = 0xaa;
	PLLFEED = 0x55;

	CCLKCFG = CCLKDivValue;	/* Set clock divider */

	while ( ((PLLSTAT & (1 << 26)) == 0) );	/* Check lock bit status */
    
	MValue = PLLSTAT & 0x00007FFF;
	NValue = (PLLSTAT & 0x00FF0000) >> 16;
	while ((MValue != PLL_MValue) && ( NValue != PLL_NValue) );

	PLLCON = 3;				/* enable and connect */
	PLLFEED = 0xaa;
	PLLFEED = 0x55;
	while ( ((PLLSTAT & (1 << 25)) == 0) );	/* Check connect bit status */
}


void InitLeds(void)
{
	
	FIO4DIR |= 1<<17; /* STAT1&2 as out */
	FIO4DIR |= 1<<16; 
        
        FIO0DIR |= 1<<4; // D4
	FIO0DIR |= 1<<5; // D5
	FIO0DIR |= 1<<6; // D6
	FIO0DIR |= 1<<7; // D7

	FIO4DIR |= 1<<15; // E
	FIO4DIR |= 1<<27; // RS
	FIO4DIR |= 1<<29; // RW
}


/*  Stubs for various interrupts (may be replaced later)  */
/*  ----------------------------------------------------  */

void IRQ_Routine (void) {
	while (1) ;	
}

void FIQ_Routine (void)  {
	while (1) ;	
}


void SWI_Routine (void)  {
	while (1) ;	
}


void UNDEF_Routine (void) {
	while (1) ;	
}

PLEASE HELP !!! I’M REACHING PROJECT DEADLINES :stuck_out_tongue:

zanak:
I<m trying to interface a 4x20 LCD with an LPC-2468. I sill cannot see anything on the LCD.

Hehehe! :D Hi zanak. That code sure looks familiar. :wink: You still haven't got it working?
void lcd_init(void)
{
   delay_ms(500);               //settle time delay
   lcd_nybble(0x03,0);            //reset LCD
   lcd_nybble(0x03,0);
   lcd_nybble(0x03,0);
   delay_ms(5);
   strobe_e();
   delay_us(160);
   strobe_e();
   delay_us(160);

Sending the 0x03 nybble three times without delays between will not work. You must send it once, wait 5mS and then send it twice more, waiting 160uS after each time. That’s what the two extra strobe_e() were for.

hehe yeah much familiar …

I’ve tried the code as you sad before but without any success !

I’m sure that my wiring are right , and sure for 90% that the code is correct too … but this thing is realy driving me crasy !!!

please any other suggestion ???

Zack

zanak:
hehe yeah much familiar …

I’ve tried the code as you sad before but without any success !

I’m sure that my wiring are right , and sure for 90% that the code is correct too … but this thing is realy driving me crasy !!!

please any other suggestion ???

I see you're not using the busy checking code. If you're not using the R/W line, then you should wire it to ground rather than connect it to P4.29. Connecting it to P4.29 is fine, but you have to be sure to keep it low at all times when writing to the LCD. Easier to just put a wire to ground and not have to worry about it.

futz:

zanak:
hehe yeah much familiar …

I’ve tried the code as you sad before but without any success !

I’m sure that my wiring are right , and sure for 90% that the code is correct too … but this thing is realy driving me crasy !!!

please any other suggestion ???

I see you're not using the busy checking code. If you're not using the R/W line, then you should wire it to ground rather than connect it to P4.29. Connecting it to P4.29 is fine, but you have to be sure to keep it low at all times when writing to the LCD. Easier to just put a wire to ground and not have to worry about it.

I did man ! still not working !!! I’v tested all signals with LEDs and I can control those outputs … but when it comes to the LCD it just don’t want to work !!

I use Codesourcery for compiling the program and I run it on uClinux OS.

heeeeeelp :stuck_out_tongue:

Zack

zanak:
I did man! Still not working!!! I’ve tested all signals with LEDs and I can control those outputs… but when it comes to the LCD it just don’t want to work !!

I use Codesourcery for compiling the program and I run it on uClinux OS.

I just changed my code over to fast GPIO like yours (not that you need the speed for a slow device like a LCD). Since I'd never looked at that before I thought maybe, possibly there might be something there. No change. Works just fine either way.

What board are you using? Anything else on the lines to your control pins that might be affecting it, like pullups/pulldowns etc?

What clock rate are you running your board at? My delays were written for 60MHz. If yours is clocked faster than that then you may have to adjust. Slower won’t hurt anything.

I don’t think I can be of much help without a LPC2468 to test with though.

futz:

zanak:
I did man! Still not working!!! I’ve tested all signals with LEDs and I can control those outputs… but when it comes to the LCD it just don’t want to work !!

I use Codesourcery for compiling the program and I run it on uClinux OS.

I just changed my code over to fast GPIO like yours (not that you need the speed for a slow device like a LCD). Since I'd never looked at that before I thought maybe, possibly there might be something there. No change. Works just fine either way.

What board are you using? Anything else on the lines to your control pins that might be affecting it, like pullups/pulldowns etc?

What clock rate are you running your board at? My delays were written for 60MHz. If yours is clocked faster than that then you may have to adjust. Slower won’t hurt anything.

I don’t think I can be of much help without a LPC2468 to test with though.

Maybe it’s my clock rate ! I’m running at 12 MHz speed … I have to change my PLL config to run at 60 MHz at least I think.

I gonna try this and tell you if it works .

thkx man !

Zack

zanak:
Maybe it’s my clock rate ! I’m running at 12 MHz speed … I have to change my PLL config to run at 60 MHz at least I think.

I gonna try this and tell you if it works .

Going too slow won't hurt delay based LCD code a bit. It should work fine. Going too fast would be a problem. The delays would have to be adjusted to suit then.

So your 12MHz clock should work fine. As long as you aren’t clocked at higher than 60MHz it should be fine.

futz:

zanak:
Maybe it’s my clock rate ! I’m running at 12 MHz speed … I have to change my PLL config to run at 60 MHz at least I think.

I gonna try this and tell you if it works .

Going too slow won't hurt delay based LCD code a bit. It should work fine. Going too fast would be a problem. The delays would have to be adjusted to suit then.

So your 12MHz clock should work fine. As long as you aren’t clocked at higher than 60MHz it should be fine.

Hi futz ,

It’s not fine at all, it still not working … damn ! I really don’t know how to solve this problem.

maybe I should buy a logic analyzer :frowning:

Zack

zanak:
It’s not fine at all, it still not working … damn ! I really don’t know how to solve this problem.

First thing to try is another LCD just to confirm that there's no problem with that one.

Have you tried stepping through the LCD init function in the debugger? If there’s any problem with your delays, stepping through the init should make it work. If it works stepping but not running then you know your delays are too short.

maybe I should buy a logic analyzer :frowning:

Shouldn't be necessary (though I love my [[Logic](http://www.saleae.com/logic/)). I got lots of LCDs working without one.](http://www.saleae.com/logic/)

I’m sure you’ve already checked these, but I’ll ask them anyway.


Have you set the contrast correctly. You should see two lines of black bars (1 and 3) - not too black - kind of halfway black. (Or white if it’s a reverse LCD (see below).)


If it’s a reverse LCD, is the backlight on? These LCDs make the characters out of non-displaying LCD blocks and shine the backlight through them like this:

http://ghmicro.com/images/stories/PIC/1 … d006sm.jpg

Without a backlight they don’t look like much.


Do you have enough power to run the LCD properly. This one bit me before. The power supply wasn’t good enough and though the LCD was displaying, I couldn’t see it. It was too faint.

futz:

zanak:
It’s not fine at all, it still not working … damn ! I really don’t know how to solve this problem.

First thing to try is another LCD just to confirm that there's no problem with that one.

Have you tried stepping through the LCD init function in the debugger? If there’s any problem with your delays, stepping through the init should make it work. If it works stepping but not running then you know your delays are too short.

maybe I should buy a logic analyzer :frowning:

Shouldn't be necessary (though I love my [[Logic](http://www.saleae.com/logic/)). I got lots of LCDs working without one.[/quote]

it’s my second one, same problem. …

I tried to debug it with the IAR IDE, (in simulation mode) and i fugured out that when I try to clear the data pins P0.4:5:6:7 the values in the FIO0CLR registers remains the same ! so the output is corrupted with earlier operations.

   FIO0CLR |= 1<<4; // D4 

FIO0CLR |= 1<<5; // D5
FIO0CLR |= 1<<6; // D6
FIO0CLR |= 1<<7; // D7

[\code]

I googled the problem, and I found that someone says that the simulator has a bug ! so I can’t take it as a reference !!

that’s why I’m buying the logic analyzer, and yeah the same as yours (I saw it on your website BTW)

concerning the code I used the the FIOMASKs but the results remains the same (in simulation mode)

Zack


](http://www.saleae.com/logic/)

Another thought: How are you powering your LCD? Does it have its own 5V supply? Or are you powering it with 3.3V, same as the ARM board?

The reason I ask is that if you’re powering it with 3.3V I read somewhere that you need to do the contrast with a negative voltage. One guy was doing it with an AAA cell. Here’s a quote:

To find out if my lcd worked at 3.3v all I did was use a single cell alkaline battery to do the offset for the contrast.Connect the positive of the battery to the ground and the negative to the contrast pot leg that would normally go to your ground.

zanak:
I tried to debug it with the IAR IDE, (in simulation mode) and i fugured out that when I try to clear the data pins P0.4:5:6:7 the values in the FIO0CLR registers remains the same ! so the output is corrupted with earlier operations.

Better check that out with some LEDs or a meter. Those bits MUST be cleared first if you're going to OR new bits into them.

futz:
I’m sure you’ve already checked these, but I’ll ask them anyway.


Have you set the contrast correctly. You should see two lines of black bars (1 and 3) - not too black - kind of halfway black. (Or white if it’s a reverse LCD (see below).)


If it’s a reverse LCD, is the backlight on? These LCDs make the characters out of non-displaying LCD blocks and shine the backlight through them like this:

Without a backlight they don’t look like much.


Do you have enough power to run the LCD properly. This one bit me before. The power supply wasn’t good enough and though the LCD was displaying, I couldn’t see it. It was too faint.

I don’t use a poto , my V00 is set to +5V (the highest contrast) but I don’t see any black lines !

it’s not a reverse LCD , but still, the backlight is on .

yeah I have enough power I guess , sine the backlight is really bright !

this thing is really weird :S

Zack

zanak:

   FIO0CLR |= 1<<4; // D4 

FIO0CLR |= 1<<5; // D5
FIO0CLR |= 1<<6; // D6
FIO0CLR |= 1<<7; // D7

Why are you not just doing ``` FIO0CLR = 0x000000f0; ``` Seems to me to be so much more simple and obvious.

zanak:
I don’t use a pot , my V00 is set to +5V (the highest contrast) but I don’t see any black lines !

If your contrast is adjusted correctly you should see two rows of blocks like these (lines 1 & 3), but in black rather than white (I don't have a photo of the 20x4 doing blocks). You'll see them when the LCD is powered up, but not initialized.

http://ghmicro.com/images/stories/LPC20 … t001sm.jpg

If contrast is set incorrectly you won’t see anything at all. :wink: Get a 10K pot and wire that thing up properly so you can adjust contrast. If you don’t have a pot, try a 1K or 1.2K resistor to ground.

It’s very possible this is all your problem is. If you don’t see blocks when you power up the LCD without running your code, then contrast IS the problem.

zanak:
I don’t use a pot , my V00 is set to +5V (the highest contrast) but I don’t see any black lines !

I'm pretty sure that's backward. Max contrast is a wire direct to ground. You have your contrast set to minimum, meaning you'll never see ANYTHING on the screen, EVER.

Once more, you MUST see two rows of blocks when the LCD is powered up but not initialized. If you don’t see them then you have a contrast problem.

futz:

zanak:
I don’t use a pot , my V00 is set to +5V (the highest contrast) but I don’t see any black lines !

I'm pretty sure that's backward. Max contrast is a wire direct to ground. You have your contrast set to minimum, meaning you'll never see ANYTHING on the screen, EVER.

Once more, you MUST see two rows of blocks when the LCD is powered up but not initialized. If you don’t see them then you have a contrast problem.

you are right, now the V0 is grounded , and i can see two lines … but I can’t see the magic words “LPC2468 LCD it Works !”

maan its driving me crazy

zanak:
you are right, now the V0 is grounded , and i can see two lines … but I can’t see the magic words “LPC2468 LCD it Works !”

Well at least you're closer than you were before. :D

You see two lines of blocks? After initialization those should disappear and you should see a blinking underscore cursor (and some text of course). If the blocks don’t go away when you run the program then the problem is the init, or the lcd-nybble routines.

Now go and take out all the crazy, grasping-at-straws changes you made to the code while trying to make it work with bad contrast. :wink: Then it’ll probably work.

you are right, now the V0 is grounded , and i can see two lines … but I can’t see the magic words “LPC2468 LCD it Works !”

Too much contrast can be as bad as too little. Tune it down a bit with the resistor I mentioned, or get a pot in there.