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.

C Driver for LCD 16X1 help please

Status
Not open for further replies.

GrandAlf

Advanced Member level 2
Joined
Mar 9, 2002
Messages
520
Helped
47
Reputation
92
Reaction score
6
Trophy points
1,298
Location
UK
Activity points
4,730
I am using a 16x1 LCD which is electrically configured as 2x8, to get to the second line, I have to add 0x40 to the display position. Eg home position is 0x80, second line is 0x80+0x40 = (0xC0). At the moment I am doing this in the main program by splitting messages in half and adding 0x40 to the position before writing the second half. This however is not very elegant, and I would like to do this automatically with lcd prog. I have had a few attempts at this, but with limited success. Any advice much appreciated.


LCD.H

/*
* LCD interface header file
* See lcd.c for more info
*/

/* 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_puts(const char * s);

/* Go to the specified position */

extern void lcd_goto(unsigned char pos);

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

extern void lcd_init(void);

extern void lcd_putch(char);

/* Set the cursor position */

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



LCD.C

#include <reg51.h>
#include "delay.h"

sbit LCD_RS =P1^0; // Register select
sbit LCD_E =P1^1; // Enable

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

// Time in Milliseconds
void DelayMs(unsigned char cnt)
{ cnt=2*cnt;
do
{DelayUs(500);}
while(--cnt != 0);
}

// Send to Display
void lcd_write(unsigned char c)
{
unsigned char Movit;
Movit = (c >> 2);
P1 = (P1 & 0xC3) | (Movit & 0x3C);
LCD_STROBE;
Movit = (c << 2);
P1 = (P1 & 0xC3) | (Movit & 0x3C);
LCD_STROBE;
DelayUs(60);
}

// Clear and home the LCD
void lcd_clear(void)
{
LCD_RS = 0;
lcd_write(0x80);
DelayMs(2);
}

// Send Character String
void lcd_puts(const char * s)
{
LCD_RS = 1;
while(*s)
lcd_write(*s++);
}

// Send a Character
void lcd_putch(char c)
{
LCD_RS = 1;
lcd_write(c);
}

// Position the Cursor
void lcd_goto(unsigned char pos)
{
LCD_RS = 0;
lcd_write (0x80+pos);
}

// Initialise the LCD - mode 4 bits
void lcd_init(void)
{
LCD_RS = 0;
DelayMs(40); // power on delay
lcd_write(0x28); // 4 bit mode, 1/16 duty, 5x8 font
LCD_STROBE;
DelayMs(5);
LCD_STROBE;
DelayMs(5);
LCD_STROBE;
lcd_write(0x28);
lcd_write(0x08); // display off
lcd_write(0x0C); // display on, cursor off
lcd_write(0x06); // entry mode
}
 

Hi,

you can use this code that i know it works on the PICDEM2 demo board.
 

maybe you to get idea





void lcd_puts(const char * s)
{
LCD_RS = 1;
poz=home position;
while(*s)
lcd_write(*s++);
poz=poz+one poz;// or poz++;
if(poz> end of first row poz && poz< home poz of second row){
poz=second row home position;
lcd_goto(poz);

}

if(poz>end of second row){
poz=home position of first row;
lcd_goto(poz);
}


}
 

Thanks Gidimiz,

If I do nor have any luck with the current driver, I will give this one a go. Than you.

Grabik,

Thanks for the info, I can still only get the first 8 chars displayed using your method. What you suggested is similar to what I have already tried, neither seem to work.

This was what I tried before with no luck.

// Position the Cursor
void lcd_goto(unsigned char pos)
{
LCD_RS = 0;
lcd_write (0x80+pos);
}

// Send Character String
void lcd_puts(const char * s)
{
unsigned char cursor = 0x00;
LCD_RS = 1;
while(*s)
lcd_write(*s++);
cursor++;
if (cursor>0x08)lcd_goto(0x40);
if (cursor>0x10)lcd_goto(0x00);
}

As you can see it is similar to what you suggested, I must be missing something obvious. Not very experienced in C yet.
 

GrandAlf,

try changing this:
if (cursor==0x08)lcd_goto(0x40);
if (cursor==0x10){cursor=0;lcd_goto(0x00);}

best regards
 

Thanks C-Man,

Sadly this does not work either. However if I change 0x80 to 0xc0 in lcd_goto, writing to the lcd now begins at position 9 as one would expect. So why is it that adding 0x40 does not do the same thing. Problem must be in lcd_puts I think. Probably so obvious that I cannot see it. I am assuming cursor is actually incremented at every character of course. Driving me mad this one!!!!
 

I cant find the LCD_STROBE (enable) after the new cursor position is sent...? or is it me?
 

Hi,

Ok now i understnad your problem. First read this:
During initializiation, by setting the "S/C" bit during the "Move Cursor/Shift Display" command, after each character is sent to the LCD, the cursor built into the LCD will increment to the next position (either right or left).

So you have to set the currser to start at the second line, first position! Only then any char you will send will be placed at the right place. If you looked at my code that i gave you, you would have seen that there is a function that is doing just that:
void Line_2( void ) // Set to line2/position 1
{
Write_Lcd_Cmd (0xC0 );
}
So you have to do 0xC0 and you cant just use 0x40.
 

GrandAlf try this modified subroutine:

// Send Character String
void lcd_puts(const char * s)
{
unsigned char cursor = 0x00;
LCD_RS = 1;
while(*s)
{
lcd_write(*s++);
cursor++;
if (cursor==0x08)lcd_goto(0x40);
if (cursor==0x10){cursor=0;lcd_goto(0x00);}
}
}
 

Thanks everyone.

C-Man,
I already tried the curly brackets, no joy. lcd_write(*s++) only works if directly following while(*s). If you put it at the end of the if statements, it does not work. I am assuming that cursor variable never gets incremented or if statments are never reached.

I know that if I directly pass 0x40 to lcd_goto it works and puts the cursor to the right location at the beginning of the second line, but it seems that lcd_puts is not achieving this for some reason.

I am tempted to try and alter gidimiz's prog to work with the 8082 and the port that I am using. It would be easier though if I could get the current problem solved.

Thanks again to all of you, your advice is always appreciated.
 

OK my last modified version (for today) :)

// Send Character String
void lcd_puts(const char * s)
{
unsigned char cursor = 0x00;

while(*s)
{
LCD_RS = 1;
lcd_write(*s);
s++;
cursor++;
if (cursor==0x08)lcd_goto(0x40);
if (cursor==0x10){cursor=0;lcd_goto(0x00);}
}
}
 

Thank you C-Man yet again. I am sure that you will be pleased to know that it now works. Wonderful help, thank you so much. I have been looking at it too long and missed the obvious !!!!!!!!!
 

Glad to help my boss often says to me that I am one of the very few that can "see in the dark" :)

best regards
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top