LCD PIC16F877A Troubles

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Hi all,

I have been stuck lately with classes, course projects and assignments so I couldn't make much progress on the personal projects front. I recently bought a PICKit 2 clone USB ICSP programmer and have been trying to get an LCD working on my breadboard. Here's the code

Rich (BB code):
//main.c
//Driver software for LCD


#include<htc.h>
#define _XTAL_FREQ 20000000

__CONFIG(FOSC_HS & LVP_OFF & CP_OFF & CP_OFF & BOREN_OFF & DEBUG_OFF & WDTE_OFF & PWRTE_OFF);
					
#define DATA PORTC				//data bus
#define BUSY RC7				//busy flag
#define ENABLE RD0				//enable signal
#define RW RD1			//read/write signal (R=1/W=0)
#define RS RD2				//register select (Text=1, Instructions=0)

#define SETBIT(x) x=x||1
#define CLRBIT(x) x=x&&0

void Push()			//push data into the LCD
{
	SETBIT(ENABLE);	
	CLRBIT(ENABLE);
}

void LCD_Busy()
{
	TRISC7=1;		//RC7 as input
	CLRBIT(ENABLE);
	SETBIT(RW);			//read mode
	CLRBIT(RS);			//instructions
	while(1)			//code execution halted until LCD is busy
	{
		SETBIT(ENABLE);
		if(!BUSY)
			break;
		CLRBIT(ENABLE);
	}
	CLRBIT(ENABLE);
	CLRBIT(RW);			//write mode
	TRISC7=0;
}

void Init()
{
	TRISC=0x00;			//PORTC as output
	TRISD0=0;
	TRISD1=0;
	TRISD2=0;			//control signals
}



void LCD_Init()
{
	CLRBIT(ENABLE);		//deactivate LCD
	SETBIT(RW);			//write mode
	CLRBIT(RS);			//write instructions
	
	//start sending instructions to the LCD		

	DATA=0x38;			//initialize two row display
	Push();				//push data onto LCD
	LCD_Busy();		//wait until LCD processes it
	DATA=0x1;			//clear LCD 
	Push();
	LCD_Busy();
	DATA=0xE;			//turn cursor ON
	Push();
	LCD_Busy();
	DATA=0x6;			//move cursor right automatically
	Push();
	LCD_Busy();
}

void LCD_Write(unsigned char ch)
{
	CLRBIT(ENABLE);
	SETBIT(RW);			//write mode
	SETBIT(RS);			//write text
	DATA=ch;
	Push();
	LCD_Busy();
}

void LCD_Clear()
{
	CLRBIT(ENABLE);		//deactivate LCD
	SETBIT(RW);			//write mode
	CLRBIT(RS);			//write instructions
	DATA=0x1;			//clear LCD 
	Push();
	LCD_Busy();
}

void main()
{
	Init();
	LCD_Init();
	LCD_Write('H');
	
	LCD_Write('E');
	LCD_Write('L');
	LCD_Write('L');
	LCD_Write('O');
	LCD_Write('!');
}
I have single-stepped through the code in hardware with no results. I have been programming 8051 chips for my microcontroller course recently and seem to have forgotten some PIC basics so kindly excuse any apparent stupid mistake. I did consider that there might be something wrong with the hardware setup as well as the LCD but I just wanted to be sure of the firmware first.

Thanks!
 

t06afre

Joined May 11, 2009
5,934
It is an example for using LCD display in the HI-Tech C samples folder. Contains both 4 and 8 bit data bus. You should also know that the busy pin on the LCD do not work in the early stages then setting up the LCD. Here you have to use some kind of timing in the software
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Tried replacing the polling routine with delays and didn't achieve any significantly different results.

I am beginning to think this is more of a hardware problem than a firmware one. I might have to solder my LCD to the header after all, I suppose.

Could it be a buggy breadboard issue? I just wanted to confirm that the code is alright so I can proceed further with the troubleshooting.
 

t06afre

Joined May 11, 2009
5,934
To me it looks like you are using PORTC for data. And at the same time RC7 for the the bussy line. Which PIC are you using? For your own sake draw a schematic and post it here. Making the schematic will make things more clear for you self and us ;) Have you had any success making a small LED blinking program. Just to check if your PIC is alive?
 

MMcLaren

Joined Feb 14, 2010
861
Aren't you supposed to use a '0' for Write and a '1' for Read on the RW line? Based on your comments, you seem to be doing it both ways...
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
@MMcLaren: Oh! I did not notice that. Thanks a lot for pointing that out. I'll make the correction asap. I have always been a little confused as far as these control signals go.

Rich (BB code):
//main.c
//Driver software for LCD


#include<htc.h>
#define _XTAL_FREQ 20000000

__CONFIG(FOSC_HS & LVP_OFF & CP_OFF & CP_OFF & BOREN_OFF & DEBUG_OFF & WDTE_OFF & PWRTE_OFF);
					
#define DATA PORTC				//data bus
#define BUSY RC7				//busy flag
#define ENABLE RD0				//enable signal
#define RW RD1			//read/write signal (R=1/W=0)
#define RS RD2				//register select (Text=1, Instructions=0)

#define SETBIT(x) x=x|1
#define CLRBIT(x) x=x&0

void Push()			//push data into the LCD
{
	SETBIT(ENABLE);	
	CLRBIT(ENABLE);
}

/* void LCD_Busy()
{
	TRISC7=1;		//RC7 as input
	CLRBIT(ENABLE);
	SETBIT(RW);			//read mode
	CLRBIT(RS);			//instructions
	while(1)			//code execution halted until LCD is busy
	{
		SETBIT(ENABLE);
		if(!BUSY)
			break;
		CLRBIT(ENABLE);
	}
	CLRBIT(ENABLE);
	CLRBIT(RW);			//write mode
	TRISC7=0;
}		*/

void Init()
{
	TRISC=0x00;			//PORTC as output
	TRISD0=0;
	TRISD1=0;
	TRISD2=0;			//control signals
}



void LCD_Init()
{
	CLRBIT(ENABLE);		//deactivate LCD
	CLRBIT(RW);			//write mode
	CLRBIT(RS);			//write instructions
	
	//start sending instructions to the LCD		

	DATA=0x38;			//initialize two row display
	Push();				//push data onto LCD
	__delay_ms(2);		//wait until LCD processes it
	DATA=0x1;			//clear LCD 
	Push();
	__delay_ms(2);
	DATA=0xE;			//turn cursor ON
	Push();
	__delay_ms(2);
	DATA=0x6;			//move cursor right automatically
	Push();
	__delay_ms(2);
}

void LCD_Write(unsigned char ch)
{
	CLRBIT(ENABLE);
	CLRBIT(RW);			//write mode
	SETBIT(RS);			//write text
	DATA=ch;
	Push();
	__delay_ms(2);
}

void LCD_Clear()
{
	CLRBIT(ENABLE);		//deactivate LCD
	CLRBIT(RW);			//write mode
	CLRBIT(RS);			//write instructions
	DATA=0x1;			//clear LCD 
	Push();
	__delay_ms(2);
}

void main()
{
	Init();
	LCD_Init();
	LCD_Write('H');
	LCD_Write('E');
	LCD_Write('L');
	LCD_Write('L');
	LCD_Write('O');
	LCD_Write('!');
	
}
@t06afre: Yup, I should have posted the picture of the circuit along with the schematic. Sorry for the lack of information.

And yes, I did try the LED blink and the PIC is alive. But when I tried lighting an LED in response to a pushbutton the pin which should have been 0V initially put out some weird voltage value like 2.2 V. I tried changing the output pin to something else and ended up with the same arbitrary (seemingly) value. Anything wrong with the code?

PS: I seem to have missed adding a resistor to ground near the pushbutton to stablize the 0 state. I'll make that correction but that doesn't have much to do with the 2.2 V output, does it?

Rich (BB code):
//main.c
//To light an LED in response to a button press

#include<htc.h>
#define _XTAL_FREQ 20000000

__CONFIG(FOSC_HS & LVP_OFF & BOREN_OFF & CPD_OFF & CP_OFF & PWRTE_OFF & WDTE_OFF & DEBUG_ON);

#define SW RD0
#define LED RC4
#define INIT RD2



unsigned int num=2;

void init()
{
	TRISD0=1;			//switch input
	TRISC4=0;				//button press
	TRISD3=0;		//initialized
	INIT=1;
	LED=0;
}

void main()
{
	init();
	while(1)
	{
		if(SW)
			LED=1;
		else
			LED=0;
			
	}	


}
In the meantime, I'll try wiring up the LCD again. Hope for better luck this time!
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Thanks for that handy tip ;)

I am stuck at the 2.4 V level. It doesn't switch high or low at the pin. Any suggestions?
 

John P

Joined Oct 14, 2008
2,026
The usual way to wire up a switch to a processor is to have the switch go between the pin and Gnd, and a resistor between the pin and Vcc. But it should also work the other way (switch to Vcc, resistor to Gnd). However, if you used a pin of PortB, you could use the internal weak pullups, and leave out the external resistor.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
UPDATE: I wired the pull-up and the switch worked! It was a very stupid mistake with the delay time not enough to light up the LED and as a result the voltage was 2.5 V!

UPDATE 2: On an unrelated note, I just switched off power to the MCU reset (active low) and the pin on which I had connected the initialization LED seems to be stuck at 2.5 V. No clue why, the rest of them having gone to 0 V. Any ideas?

I'll connect the LCD and serial port in the meantime.

Thanks for all the help! :)
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Sorry for the late follow-up on this thread but on a good note: The LCD worked! It was a hardware problem and apparently the wire connections weren't properly made. I'll try the rest of the code and let you know how it goes.

Thanks for all the help!
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Hi,

I have been playing around with various display effects on my LCD ever since I got it working. While everything looks fine, the program runs as if it is in a loop. The sentences, while clearly formed, are unsteady and keep sort of blinking/reloading.

I had to introduce a 500 ms delay to make it steadier, which did not help much.
While I do realize LCD controllers are a little slow but could this be a problem with the software?

Does the PIC run the whole code in an infinite loop by itself even when you haven't instructed it to do so? Or is there a configuration setting I might have messed up?

In general, what happens to an embedded program when we don't run it continuously or when the main function ends?

PS: I can attach the Proteus simulation file if required.

Thanks!
 

spinnaker

Joined Oct 29, 2009
7,830
Hi,


While I do realize LCD controllers are a little slow but could this be a problem with the software?

Does the PIC run the whole code in an infinite loop by itself even when you haven't instructed it to do so? Or is there a configuration setting I might have messed up?

In general, what happens to an embedded program when we don't run it continuously or when the main function ends?

PS: I can attach the Proteus simulation file if required.

Thanks!
Sorry I have no idea what you are asking maybe others can figure it out.

Your code will do (usually baring an internal bugs) exactly what you tell the mcu to do.

A pic needs to have one main infinite loop to run properly. The main function should never end.


I am guessing you have more hardware issues. Have you tried using your debugger to verify everything?
 

MrChips

Joined Oct 2, 2009
30,823
In general, what happens to an embedded program when we don't run it continuously or when the main function ends?
An embedded application never ends. You create an endless loop and you don't exit the main function.

Rich (BB code):
void main(void)
{
   Initialization();
   while (1)
   {


   }
}
 

John P

Joined Oct 14, 2008
2,026
In general, what happens to an embedded program when we don't run it continuously or when the main function ends?
Thanks!
This is a situation you usually want to avoid. If your code reaches the end of the main() function, it will continue to execute instructions in whatever memory locations are beyond the programmed area. If the chip was erased, this most likely means successive words containing all 1's, so you can look up whatever that is for your processor to see what it does. If the chip wasn't erased, but new code was just written over old, then you might find you're executing code left over from whatever was last written to the chip--either an old version of your current program or something totally different. But if by some chance the code reaches the end of the memory, it'll wrap around to 0000 and start running code from the beginning, but maybe with improper settings in place. A satisfactory result is unlikely!

There are various things you can do if you want to stop executing code and wait for a reset: turn off everything and put an endless loop at the end of your code, or a sleep() instruction.
 

takao21203

Joined Apr 28, 2012
3,702
It depends but I sometimes see PICs self-resetting after some 100 msec., due to banking, register trashing, or stack overflow issues. Sometimes this does not always become evident immediately.

Weird blink or flicker patterns could mean there is something wrong with banking, register access or the stack, and the PIC is trapped in a constant process of self-resetting.
 

xainnasir

Joined Nov 8, 2012
15
which compiler u r using ..... try mikroC they have complete ecample in the help section .... just copy paste it .... schematic is also given there
 

ErnieM

Joined Apr 24, 2011
8,377
It looks like your main() function ends... In a PC that would return control to the operating system. In an embedded project it just calls main() over and over.


To get a C program to stop add a while(1); line.
 

Thread Starter

ActivePower

Joined Mar 15, 2012
155
Thanks for all the help. Turns out the main() was looping on itself as most of you pointed out. From what I read elsewhere the behavior in such cases is uncertain and needs to be controlled using a while() loop. I added an infinite loop at the end and it seems to have sorted out the issue.

Will keep you updated on the project!

Thanks for all the prompt replies! :)
 
Top