Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD Interface problem with 16f877a

Status
Not open for further replies.

pany2008

Junior Member level 3
Joined
Aug 24, 2009
Messages
30
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
India
Activity points
1,627
Hi
I am using the 16x2 lcd and interfacing it with 4 bit mode, i am placing the source please suggest what is wrong, the display is showing only the cursor blink but it is not displaying the message.

main program

#include<pic.h>
#include "ioports1.h"
#include "delay.h"
#include "lcd.h"

__CONFIG (DEBUGDIS & WDTDIS & BORDIS & PWRTDIS & HS & LVPDIS & PROTECT);

extern init_ports();

void Sec(unsigned int);

void main()
{

init_ports();
Sec(200);
lcd_init(); //LCD initialized
Sec(100);
lcd_line1(0); //LCD address specified AT LINE 1
lcd_string("INTERFACING LCD"); //Displays message "LCD INTERFACING"
lcd_line2(0); //LCD address specified AT LINE 2
lcd_string(" PIC 16F877A");//Displays message " PIC 16f877a"

for(;;)
{

LED1 = !LED1;
Sec(300);
LED1 = !LED1;
Sec(300);
}
}

init_ports()
{
T_LED1 = 0; // pin enable to output
LED1 = 1;
T_LED2 = 0; // pin enable to output
LED2 = 1;
T_LED3 = 0; // pin enable to output
LED3 = 1;
}

void Sec(unsigned int itime)
{
unsigned int i;
unsigned char j;
for(i=0;i<itime;i++)
for(j=0;j<165;j++);
}

lcd.c file code

#include <htc.h>
#include "lcd.h"
#include "ioports.h"

//#define LCD_RS RB6
//#define LCD_RW RB5
//#define LCD_EN RB4

#define LCD_DATA PORTB

#define LCD_STROBE() ((LCD_EN = 1),(LCD_EN=0))

/* write a byte to the LCD in 4 bit mode */

void
lcd_write(unsigned char c)
{
unsigned char d;

__delay_us(40);
LCD_DATA = ( ( c >> 4 ) & 0x0F );
LCD_STROBE();
LCD_DATA = (c & 0x0F);
LCD_STROBE();
__delay_us(40);
}

/*
* Clear and home the LCD
*/

void
lcd_clear(void)
{
LCD_RS = 0;
lcd_write(0x1);
__delay_ms(2);
}

/* write a string of chars to the LCD */

void
lcd_string(const char * s)
{
LCD_RS = 1; // write characters
while(*s)
lcd_write(*s++);
}

/* write one character to the LCD */

void
lcd_character(char c)
{
LCD_RS = 1; // write characters
lcd_write( c );
}


/*
* Go to the specified position in line 1
*/

void
lcd_line1(unsigned char pos)
{
LCD_RS = 0;
lcd_write(0x80+pos);
}

/*
* Go to the specified position in line 2
*/

void
lcd_line2(unsigned char pos)
{
LCD_RS = 0;
lcd_write(0xC0+pos);
}
/*
* Go to the specified position in line 3
*/

void
lcd_line3(unsigned char pos)
{
LCD_RS = 0;
lcd_write(0x94+pos);
}
/*
* Go to the specified position in line 4
*/

void
lcd_line4(unsigned char pos)
{
LCD_RS = 0;
lcd_write(0xD4+pos);
}

/* initialise the LCD - put into 4 bit mode */
void
lcd_init()
{
char init_value;

T_LCD_RS = 0; // pin enable to output
LCD_RS = 0;

T_LCD_RW = 0; // pin enable to output
LCD_RW = 0;

T_LCD_EN = 0; // pin enable to output
LCD_EN = 0;

T_LCD_D0 = 0; // pin enable to output
LCD_D0 = 0;
T_LCD_D1 = 0; // pin enable to output
LCD_D1 = 0;
T_LCD_D2 = 0; // pin enable to output
LCD_D2 = 0;
T_LCD_D3 = 0; // pin enable to output
LCD_D3 = 0;

init_value = 0x3;
// PORTB = 0x00;
// TRISB = 0x00;
LCD_RS = 0;
LCD_EN = 0;
LCD_RW = 0;

__delay_ms(15); // wait 15mSec after power applied,
LCD_DATA = init_value;
LCD_STROBE();
__delay_ms(5);
LCD_STROBE();
__delay_us(200);
LCD_STROBE();
__delay_us(200);
LCD_DATA = 2; // Four bit mode
LCD_STROBE();

lcd_write(0x28); // Set interface length
lcd_write(0xF); // Display On, Cursor On, Cursor Blink
lcd_clear(); // Clear screen
lcd_write(0x6); // Set entry Mode
}

lcd.h

/* write a byte to the LCD in 4 bit mode */

extern void lcd_write(unsigned char);

/* Clear and home the LCD */

extern void lcd_clear(void);

/* write a string of characters to the LCD */

extern void lcd_string(const char * s);

/* Go to the specified position in line 1 */
extern void lcd_line1(unsigned char pos);

/* Go to the specified position in line 2 */
extern void lcd_line2(unsigned char pos);

/* Go to the specified position in line 3 */
extern void lcd_line3(unsigned char pos);

/* Go to the specified position in line 4 */
extern void lcd_line4(unsigned char pos);

/* intialize the LCD - call before anything else */

extern void lcd_init(void);

extern void lcd_character(char);

/* Set the cursor position */

#define lcd_cursor(x) lcd_write(((x)&0x7F)|0x80)

ioports.h

#ifndef BITNUM
#define BITNUM(adr, bit) ((unsigned)(&adr)*8+(bit)) //-- used for port defs
#endif

static bit LCD_RS @ BITNUM(PORTB,6);
static bit T_LCD_RS @ BITNUM(TRISB,6);
static bit LCD_RW @ BITNUM(PORTB,5);
static bit T_LCD_RW @ BITNUM(TRISB,5);
static bit LCD_EN @ BITNUM(PORTB,4);
static bit T_LCD_EN @ BITNUM(TRISB,4);
static bit LCD_D0 @ BITNUM(PORTB,0);
static bit T_LCD_D0 @ BITNUM(TRISB,0);
static bit LCD_D1 @ BITNUM(PORTB,1);
static bit T_LCD_D1 @ BITNUM(TRISB,1);
static bit LCD_D2 @ BITNUM(PORTB,2);
static bit T_LCD_D2 @ BITNUM(TRISB,2);
static bit LCD_D3 @ BITNUM(PORTB,3);
static bit T_LCD_D3 @ BITNUM(TRISB,3);

delay.c

void
DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif

#if XTAL_FREQ > 2MHZ
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
} while(--i);
} while(--cnt);
#endif
}


delay.h

#ifndef XTAL_FREQ
#define XTAL_FREQ 12MHZ /* Crystal frequency in MHz */
#endif

#define MHZ *1000L /* number of kHz in a MHz */
#define KHZ *1 /* number of kHz in a kHz */

#if XTAL_FREQ >= 12MHZ

#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)*((XTAL_FREQ)/(12MHZ)); \
while(--_dcnt != 0) \
continue; }
#else

#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
while(--_dcnt != 0) \
continue; }
#endif

extern void DelayMs(unsigned char);


ioports1.h

#ifndef BITNUM
#define BITNUM(adr, bit) ((unsigned)(&adr)*8+(bit)) //-- used for port defs
#endif

static bit LED1 @ BITNUM(PORTD,7); //-- LED
static bit T_LED1 @ BITNUM(TRISD,7);
static bit LED2 @ BITNUM(PORTD,3); //-- LED
static bit T_LED2 @ BITNUM(TRISD,3);
static bit LED3 @ BITNUM(PORTD,2); //-- LED
static bit T_LED3 @ BITNUM(TRISD,2);

please if any one can guide me my problem
 

You should adjust your portpins to digital
ADCON1=&1010 or something like based on your compiler
 

mojtaba_mjtb said:
You should adjust your portpins to digital
ADCON1=&1010 or something like based on your compiler

Hai thanks for help but i am right now using the only PORTB for LCD display so it is not and analog input pin but its totally digital pin no need to adjust ADCON1 in it.
 

your routines / structure are generally poorly thought out, and the issues are numerous.

take for example your lcd_write() routine. Since your control lines are on the same port as your lcd, when you perform something like:

Code:
	LCD_DATA = ( ( c >> 4 ) & 0x0F );

you have destroyed the states of those non-lcd-data pins (RS/EN/RW pins).
 

Millwood is right.

These routines look like from the Hi-Tech C LCD interface example.
If you want all the pins from the same port you need to save the port state and 'or' it.

like:

Code:
 LCD_DATA = ((LCD_DATA & 0xF0) | ( c >> 4 ) & 0x0F );
 //                    XXXX 0000 | 0000 YYYY   =  XXXXYYYY
//note the last 4 bits on the port remain un changed

The Hitech C example is a bit crude because it assumes that you do not use the higher 4 bits of the port as output.
 

spiralbrain said:
The Hitech C example is a bit crude

that speaks volume about hitech, doesn't it?
 

millwood said:
that speaks volume about hitech, doesn't it?

It does kind of yes, but its the application engineers to blame. I like HiTech, been using it for quite a while now and sometimes the efficiency is brilliant. Now that its been acquired by Microchip I wonder where they are heading.
 

i just want to give suggestion, i think it much better use BASIC for display 2 x 16 lcd..u can use PICBasic or Proton IDE..for example u want display "Hello World", the command u should use is

Print at 1,1, "Hello World"
 

Here is the code for main...

Code:
	init();
	DelayMs(100);
	lcd_init();
	DelayMs(100);
	lcd_goto(0);	// select first line
	DelayMs(100);
	lcd_puts("12345678");
	DelayMs(100);
	lcd_goto(0x40);	// Select second line
	DelayMs(100);
	lcd_puts("Hello World");
	DelaySec(10);
	lcd_clear();
	DelayMs(100);

	lcd_message("Line 1",1);
	DelayMs(100);
	lcd_message("Line 2",2);
	DelayMs(100);
	lcd_message("Line 3",3);
	DelayMs(100);
	lcd_message("Line 4",4);
	DelaySec(10);
	lcd_clear();
	DelayMs(100);
 

Thanks to everyone for the great help now the lcd display is working fine with all off yours help, now i need one more help please help me.

I am posting schematic here in which i am using the key board on the 4 bit data line of lcd, and common from 4 key is taken to the PORT RB7, i am not able to sense the key, and even lcd also show some junk character in the lcd when any of the key is pressed please provide me some help.


static bit KEY1 @ BITNUM(PORTB,0); //-- KEY
static bit T_KEY1 @ BITNUM(TRISB,0);
static bit KEY2 @ BITNUM(PORTB,1); //-- KEY
static bit T_KEY2 @ BITNUM(TRISB,1);
static bit KEY3 @ BITNUM(PORTB,2); //-- KEY
static bit T_KEY3 @ BITNUM(TRISB,2);
static bit KEY4 @ BITNUM(PORTB,3); //-- KEY
static bit T_KEY4 @ BITNUM(TRISB,3);
static bit KEY_RT @ BITNUM(PORTB,7); //-- KEY
static bit T_KEY_RT @ BITNUM(TRISB,7);

static bit LCD_RS @ BITNUM(PORTB,6);
static bit T_LCD_RS @ BITNUM(TRISB,6);

static bit LCD_RW @ BITNUM(PORTB,5);
static bit T_LCD_RW @ BITNUM(TRISB,5);

static bit LCD_EN @ BITNUM(PORTB,4);
static bit T_LCD_EN @ BITNUM(TRISB,4);


for loop routine

for(;;)
{
key_check();
copy_adc_values();
convert_adc_temp_values();
convert_adc_pt_values();
update_lcd();
}


Key check routine

key_check()
{
T_LCD_RW = 0;
LCD_RW = 1;
T_LCD_RS = 0;
LCD_RS = 1;
T_LCD_EN = 0;
LCD_EN = 0;

T_KEY1 = 0; // pin enable to output
T_KEY2 = 0; // pin enable to output
T_KEY3 = 0; // pin enable to output
T_KEY4 = 0; // pin enable to output

T_KEY_RT = 1; // pin enable to input
KEY_RT = 1;

KEY1 = KEY2 = KEY3 = KEY4 = 1;

++key_cnt;
switch(key_cnt)
{
case 1: KEY1 = 0;
KEY2 = KEY3 = KEY4 = 1;
break;
case 2: KEY2 = 0;
KEY1 = KEY3 = KEY4 = 1;
break;
case 3: KEY3 = 0;
KEY2 = KEY1 = KEY4 = 1;
break;
case 4: KEY3 = 0;
KEY2 = KEY3 = KEY1 = 1;
break;
}

switch(key_cnt)
{
case 1: if(!KEY_RT)
{
up_flag = 1;
key1_flag = 1;
keyno = 1;
}
else if(KEY_RT)
{
up_flag = 0;
key1_flag = 0;
}
break;
case 2: if(!KEY_RT)
{
dn_flag = 1;
key2_flag = 1;
keyno = 2;
}
else if(KEY_RT)
{
dn_flag = 0;
key2_flag = 0;
}
break;
case 3: if(!KEY_RT)
{
set_flag = 1;
key3_flag = 1;
keyno = 3;
}
else if(KEY_RT)
{
set_flag = 0;
key3_flag = 0;
}
break;
case 4: if(!KEY_RT)
{
ent_flag = 1;
key4_flag = 1;
keyno = 4;
}
else if(KEY_RT)
{
ent_flag = 0;
key4_flag = 0;
}
break;
}

if(key_cnt >= 5) key_cnt = 0;

if((key1_flag) || (key2_flag) || (key3_flag) || (key4_flag)) key_flag = 1;
else if((!key1_flag) && (!key2_flag) && (!key3_flag) && (!key4_flag))
{
key_flag = 0;
keyno = 0;
}

// if(!key_flag)
// {
T_KEY_RT = 0; // pin enable to output
KEY_RT = 0;

TRISB = 0X00;
// PORTB = 0X00;
LCD_RW = 0;
LCD_RS = 0;
// }
}
 

I am using PIC16F628A with 2x16 lcd and hi tech c example. I modified this example for my case. I am using RB0 for external interrupt, so I can't "and" the data with lower 4 bits of PORTB, so I changed the code for higher 4 bits to compare with data. LCD initializes perfect, but it's displaying some strange chars (like @ and some chineese letters). Can someone look at my case, please?

Code:
#include	"main.h"
#ifndef	_XTAL_FREQ	
#define	_XTAL_FREQ	4000000
#endif
#define	LCD_RS RA2
#define LCD_EN RA3

#define LCD_DATA	PORTB

#define	LCD_STROBE()	((LCD_EN=1),(__delay_us(1)),(LCD_EN=0),(__delay_us(1)))

/* write a byte to the LCD in 4 bit mode */

void
lcd_write(unsigned char c)
{	
	__delay_us(45);
	LCD_DATA = (c&0xf0);	//pošljemo zgornje 4 bite
	LCD_STROBE();
	LCD_DATA = ((c>>4)&0xf0);	//pošljemo spodnje 4 bite
	LCD_STROBE();
	__delay_us(45);
}

/*
 * 	Clear and home the LCD
 */

void
lcd_clear(void)
{
	LCD_RS = 0;
	lcd_write(0x01);
	__delay_ms(3);
}

/* write a string of chars to the LCD */

void
lcd_puts(const char * s)
{
	LCD_RS = 1;	// write characters
	for(;*s;*s++)
		lcd_write(*s);
}

/* write one character to the LCD */

void
lcd_putch(char c)
{
	LCD_RS = 1;	// write characters
	lcd_write( c );
}


/*
 * Go to the specified position
 */

void
lcd_goto(unsigned char pos)
{
	LCD_RS = 0;
	lcd_write(0x80+pos);
}
	
/* initialise the LCD - put into 4 bit mode */
void
lcd_init()
{
	__delay_ms(40);	// zakasnitev za stabilizacijo elektronike LCD-ja
	LCD_RS=0;
	LCD_DATA=0x3;
	LCD_STROBE();
	__delay_ms(10);
	LCD_DATA=0x3;
	LCD_STROBE();
	__delay_us(200);
	LCD_DATA=0x3;
	LCD_STROBE();
	__delay_ms(5);
	LCD_DATA=0x2;
	LCD_STROBE();
	__delay_us(200);
	lcd_write(0x28);
	lcd_write(0x08);
	lcd_clear();
	lcd_write(0x06);
	lcd_write(0x0f);
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top