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.

16x1 LCD only shows 8 leftmost characters

Status
Not open for further replies.

karan123

Member level 3
Joined
Feb 2, 2009
Messages
55
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,710
lcd only 8 characters

Hello,

I have written ASM Program for 16 x 1 LCD (with no auxiliary driver) means one IC (or epoxy blob) on Back.

But I have Seen only 8 leftmost characters.

;LCD INTI ROUTINE
mov a,#38h ; 16 x 1 LCD
acall command
mov a,#0eh ; Disply on,Cursor not Blinking
acall command
mov a,#06h ; Increment Cursor
acall command
mov a,#01h ; Clear Disply
acall command
mov a,#80h ; Force Cursor to Begining of First Line
acall command


How I see next 8 Characters?

Thanks in Advance
Karan
 

lcd + 8 character

These are configured electrically as 2x8. Here is driver written in C for 8051, you may be able to pick up some idea from it.

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);
}

// 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;

while(*s)
{
LCD_RS = 1;
lcd_write(*s);
s++;
cursor++;
if (cursor==0x08)lcd_goto(0x40); // Change to 0x80 for simulation
if (cursor==0x10){cursor=0;lcd_goto(0x00);}
}
}


// 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
}

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)

DELAY.H (if needed)
#define XTAL_FREQ 12
#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)*((XTAL_FREQ)/12); \
while(--_dcnt != 0) \
continue; }

extern void DelayMs(unsigned char);

Added after 6 minutes:

Here is another from CCS site for PICS

// Flex_lcd_16x1.c

// These are randomly assigned pins, used to test
// that the driver can work with any arrangement
// of i/o pins.
#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7

#define LCD_RS PIN_B0
#define LCD_RW PIN_A2
#define LCD_E PIN_B3



// If you want to use a 6-pin interface for your LCD, then
// connect the R/W pin on the LCD to ground and comment
// out the following line. A 6-pin interface to the LCD
// is used if only have a few free i/o pins available on
// your PIC, and you want to use the smallest possible
// number of pins for the LCD.

//#define USE_LCD_RW 1

//========================================
// Use "2 lines" as the lcd type for the 16x1 LCD.
// The LCD is the same as an 8x2 LCD, but with the
// bottom line appended on the right side of the first line.
#define LCD_TYPE 2 // 0=5x7, 1=5x10, 2=2 lines
#define LCD_2ND_HALF_ADDRESS 0x40

#define LCD_WIDTH 16
#define LCD_HALF_WIDTH (LCD_WIDTH/2)

int8 const LCD_INIT_STRING[4] =
{
0x20 | (LCD_TYPE << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};

int8 lcd_xcoord;


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));

delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_us(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);
delay_us(1);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return((high << 4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(), 7)) ;
#else
delay_us(60);
#endif

if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);

delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

// Some LCDs require 15 ms minimum delay after
// power-up. Others require 30 ms. I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);

for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING);

// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}

lcd_xcoord = 1;
}

//----------------------------
// The x-coordinate can be 1 to 16.
// The y coordinate is ignored.
// This x,y interface is kept in order to be
// consistent with other CCS LCD drivers.
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

// Update the global x-coordinate variable with the
// current x coordinate.
lcd_xcoord = x;

// Convert the x-coordinate from CCS format (1-16) to
// the 0-15 format used by the LCD hardware.
address = x - 1;

// If the x-coordinate is within the 2nd half of the
// LCD line, the address must be adjusted because
// of the special architecture of the 8x2 LCD.
if(address >= LCD_HALF_WIDTH)
{
address += (LCD_2ND_HALF_ADDRESS - LCD_HALF_WIDTH);
}

lcd_send_byte(0, 0x80 | address);
}


//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
lcd_xcoord = 1;
break;

case '\n':
lcd_gotoxy(1,1); // Goto start of line 1
break;

case '\b':
lcd_send_byte(0, 0x10);
lcd_xcoord--;
if(lcd_xcoord == LCD_HALF_WIDTH)
lcd_gotoxy(LCD_HALF_WIDTH, 1);
break;

default:
lcd_send_byte(1, c);
lcd_xcoord++;
if(lcd_xcoord == (LCD_HALF_WIDTH +1))
lcd_gotoxy(LCD_HALF_WIDTH +1, 1);
break;
}
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif
 

how to initialize single line 16x1 lcd

Thanks for Reply..


But I am using LCD 16 x 1 (with no auxiliary driver on BACK SIDE of LCD)

in 8-BIT MODE.(using all LCD Signals from D0-D7)

Please Suggest me how to INITIALIZE THAT?



KARAN
 

16x1 line lcd display initialization

Hi karan123

There are two different configurations for 16x1 LCDs depending on your manufucturer.
1)the appropriate memory addresses for the 16 characters are 00h - 0Fh. This should be initialized as a 1-line device.
2)first 8 characters are at 00h - 07h and the others are at 40h - 47h. This must be initialized as a 2-line device.

after writing firs 8 characters, move your cursor to the location 40h (9th charachter) using this command: 0C0H

e.g.:
Code:
    MOV       A,#0C0H
    ACALL     COMMAND

hope this helps.Let us know the result.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top