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.

Diplaying User Defined Graphics on alphanumeric LCD

Status
Not open for further replies.

saeed_pk

Full Member level 4
Joined
May 20, 2006
Messages
237
Helped
35
Reputation
68
Reaction score
28
Trophy points
1,308
Location
Islamabad, Pakistan
Activity points
2,655
program for 20x2 alphanumeric display

HI I am using PIC16F877 with 20x2 Alphanumeric LCD , I am working on Hi-tech PICC Compiler. I want to display user defined graphics on LCD I am using LCD.H and LCD.C files provided in samples directory of PICC
please help me modifying this program that some how i could be able to Display user defined graphics on LCD.
 

pattern+cgram+lcd

not 100% sure on this but I think the Hi-tech lcd headers are designed for use with a controller such as HA44780 and their character map is in rom, so not changable :(
If i've got it wrong please link the display you are intending to use and I'll have a looksee :)
 

alphanumeric lcd rountines

If it is character LCD with "standard" controller (probably yes), you have first eight chars (code 0..7) of character generator located in CGRAM. You can define bit pattern i 5x7 pixels for each char in CGRAM a load it to LCD just after initialization. I used it many years ago to display special chars of czech language and for simple chraph (20 columns with different height 0..7 lines). I don't know about your "LCD.H" and "LCD.C", but it is easily portable thing.

Try this for example or google for LCD CGRAM:
https://www.embeddedrelated.com/usenet/embedded/show/61738-1.php

Regards Paul.
 

lcd display(user defined program)

I am uploading LCD.C and LCD.H file please see

// LCD.H
Code:
#ifndef _LCD_H_
#define _LCD_H_

#ifdef CHECKBUSY
	#define	LCD_WAIT lcd_check_busy()
#else
	#define LCD_WAIT DelayMs(5)

#endif

#define MESSAGE_LINE		0x0

#define LCD_RS	RD1
#define LCD_RW	RD2 
#define LCD_EN	RD0

#define LCD_DATA	PORTD
#define LCD_DATA_PORT	PORTD
#define LCD_RS_TRIS	TRISD1
#define LCD_RW_TRIS	TRISD2
#define LCD_EN_TRIS	TRISD0

#define LCD_DATA_TRIS	TRISD

#define FIRST_LINE	0x00
#define SECOND_LINE	0x40
#define THIRD_LINE	0x14
#define FOURTH_LINE	0x54	
#define CURSOR_SHIFT_LEFT	0x10
#define FOURBIT_MODE	0x0
#define EIGHTBIT_MODE	0x1
#define OUTPUT_PIN      0x0	
#define INPUT_PIN       0x1	
#define OUTPUT_DATA     0x0	
#define INPUT_DATA      0x0F
#define CURSOR_BLINK_OFF	0xC	

#define LCD_STROBE()	LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0

#define LCD_STROBE_READ(value)	LCD_EN = 1; \
				asm("nop"); asm("nop"); \
				value=LCD_DATA_PORT; \
				LCD_EN = 0; 

#define	lcd_cursor(x)			lcd_cmd(((x)&0x7F)|0x80)
#define lcd_clear()			lcd_cmd(0x1)
#define lcd_putch(x)			lcd_data(x)
#define lcd_goto(x)			lcd_cmd(0x80+(x));
#define lcd_cursor_right()		lcd_cmd(0x14)
#define lcd_cursor_left()		lcd_cmd(0x10)
#define lcd_display_shift()		lcd_cmd(0x1C)
#define lcd_home()			lcd_cmd(0x2)

extern void lcd_cmd(unsigned char);
extern void lcd_data(unsigned char);
extern void lcd_puts(const char * s);
extern void lcd_init(unsigned char);

#endif



LCD.C

Code:
/*
 *	LCD interface example
 *	Uses routines from delay.c
 *	This code will interface to a standard LCD controller
 *	like the Hitachi HD44780. It uses it in 4 or 8 bit mode
 *	
 */

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

static bit fourbit;		// four or eight bit mode?

#ifdef CHECKBUSY

unsigned char 
lcd_read_cmd_nowait(void)
{
	unsigned char c, readc;

	LCD_DATA_TRIS	 = INPUT_DATA;

	LCD_RW = 1; // Read LCD
	asm("nop"); // short propagation delay
	asm("nop"); // short propagation delay

	if (fourbit)
	{
		LCD_STROBE_READ(readc); // Read high nibble
		// Move 4 bits to high nibble while zeroing low nibble
		c = ( ( readc << 4 ) & 0xF0 ); 
		LCD_STROBE_READ(readc); // Read low nibble
    		c |= ( readc & 0x0F ); // Or in 4 more bits to low nibble
	}
	else
	{
		LCD_STROBE_READ(readc); 
		c = readc;
	}
	LCD_RW = 0; // Return to default mode of writing LCD
	LCD_DATA_TRIS	 = OUTPUT_DATA; // Return to default mode of writing LCD

	return(c);
}

void
lcd_check_busy(void) // Return when the LCD is no longer busy, or we've waiting long enough!
{
	// To avoid hanging forever in event there's a bad or 
	// missing LCD on hardware.  Will just run SLOW, but still run.
	unsigned int retry; 
	unsigned char c;

	for (retry=1000; retry-- > 0; ) {
		c = lcd_read_cmd_nowait();
		if (0==(c&0x80)) break; // Check busy bit.  If zero, no longer busy
	}
}

#endif

/* send a command to the LCD */
void
lcd_cmd(unsigned char c)
{
	LCD_WAIT; // may check LCD busy flag, or just delay a little, depending on lcd.h

	if (fourbit)
	{
		LCD_DATA = (  c  & 0xF0 );
		LCD_STROBE();
    		LCD_DATA = ( ( c << 4) & 0xF0 );
		LCD_STROBE();
	}
	else
	{
		LCD_DATA = c;
		LCD_STROBE();
	}
}

/* send data to the LCD */
void
lcd_data(unsigned char c)
{
	LCD_WAIT; // may check LCD busy flag, or just delay a little, depending on lcd.h

	LCD_DATA = 0;
	LCD_RS = 1;
	if (fourbit)
	{
    		LCD_DATA |= ( c & 0xF0 );      
		LCD_STROBE();
		LCD_DATA &= 0x0F;
		LCD_DATA |= ( ( c << 4) & 0xF0 ); 
		LCD_STROBE();
	}
	else
	{
		LCD_DATA = c;
		LCD_STROBE();
	}
	LCD_RS = 0;
}

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

void
lcd_puts(const char * s)
{
	while(*s)
		lcd_data(*s++);
}

/* initialize the LCD */
void
lcd_init(unsigned char mode)
{
	char init_value;

	fourbit		= 0;
	if (mode == FOURBIT_MODE){
		fourbit = 1;
		init_value = 0x3;
	}else{
		init_value = 0x3F;
	}
	LCD_RS = 0;
	LCD_EN = 0;
	LCD_RW = 0;
	LCD_RS_TRIS	 = OUTPUT_PIN;
	LCD_EN_TRIS	 = OUTPUT_PIN;
	LCD_RW_TRIS	 = OUTPUT_PIN;
	LCD_DATA_TRIS	 = OUTPUT_DATA;
	DelayMs(15);
	LCD_DATA	 = (init_value << 4);
	LCD_STROBE();
	DelayMs(5);
	LCD_DATA	 = (init_value << 4);
	LCD_STROBE();
	DelayUs(200);
	LCD_DATA	 = (init_value << 4);
	LCD_STROBE();
	
	if (fourbit)
		{
		LCD_WAIT; //may check LCD busy flag, or just delay a little, depending on lcd.h
		LCD_DATA = (0x2 << 4); // Set 4-bit mode
		LCD_STROBE();
		lcd_cmd(0x28); // Function Set: Two Lines, 5x7 Matrix
		}
	else
		{
		lcd_cmd(0x38);
		}
	
	lcd_cmd(0xF); //Display On, Cursor On, Cursor Blink
	lcd_cmd(0x1); //Display Clear
	lcd_cmd(0x6); //Entry Mode
	lcd_cmd(0x80); //Initialize DDRAM address to zero
}

Please Check it out and tell how can i program (display) special character over it
 

cm2040 lcd

Commads dedicated for writing into CGRAM is completely missed in your LCD.C and LCD.H. Have you read any datasheet of character LCD? Try one from attachment.
On page 12 you can see complete commands for LCD control. Because character LCD drivers are compatible for long time, these commands are 100% identical with your LCD.
See "Set CGRAM address" command. Simply send 0x40 as command to your LCD. This will set CGRAM adress to 0x00 (top row of first custom char). Then you can simply write max. (7x8) 56 bytes of max. 8 custom char patterns as LCD data. After last byte you can set DDRAM to adress 0x00 (home command) and all next writes will be directed to display data RAM.
First custom char (code 0x00) definition begins on CGRAM address 0x00.
Second custom char (code 0x01) definition begins on CGRAM address 0x08.
Etc...
On page 16 is described CGRAM organization and character pattern definiton.
I'm not using first custom char 0x00, because it collides with end zero of ASCIIZ string from C language.

You can see one from my character LCD initialization routines, where four arrows are defined on custom char codes 0x01, 0x02, 0x03 and 0x04. Sorry for some czech comments. Moreover, i'm using 'blind write' to LCD without busy checking in this case.

Remember, that custom chars can be loaded to LCD at any time, so you can define different sets of custom chars a use it in relevant context (menu, information text, graph etc...).

Regards
Paul.

Code:
// CM2040.C - Write only 4x20 char LCD mapovany do ext. RAM pro Mega128

#include <avr/io.h>
#include "CM2040.H"
#include "GLOBALS.H"

#define portLCMData (*(volatile unsigned char *)(0x00808000)) // LCM Data port -> write only
#define portLCMCtrl (*(volatile unsigned char *)(0x00808001)) // LCM Control port 0 = E, 1 = RS -> write only

#define IniDly 10000
#define SmallDly 2500 //50 //10

static unsigned char LCMControl;

void LCWait(void) { // Cekani ~2 ms na provedeni povelu
 volatile unsigned short N;

 N = SmallDly;
 while (N)
  N--;
}

void LCPuls(void) {
 volatile unsigned char N;

 N = 5;
 while (N)
  N--;
}

void LCMClk(void) {

 LCMControl = LCMControl | 1;
 portLCMCtrl = LCMControl;
 // Wait
 LCPuls();
 LCMControl = LCMControl & (unsigned char) ~1;
 portLCMCtrl = LCMControl;
 LCWait();
}

void LcmData(unsigned char C) { // RS = 1

 LCMControl = LCMControl | 2;
 portLCMData = C;
 LCMClk();
}

void LcmCmd(unsigned char C) { // RS = 0

 LCMControl = LCMControl & (unsigned char) ~2;
 portLCMData = C;
 LCMClk();
}

void LCMInit(void) {
 volatile unsigned short I;

 portLCMCtrl = 0x00;
//RS = 0; RW = 0;
 for (I=0;I<IniDly;I++); // Wait 15ms
 LcmCmd(0x30);
 for (I=0;I<IniDly;I++); // Wait > 4.1ms
 LcmCmd(0x30);
 for (I=0;I<IniDly;I++); // Wait > 100us
 LcmCmd(0x30);
 for (I=0;I<IniDly;I++); // Wait > 100us
// Setup
 LcmCmd(0x38);
 LcmCmd(0x01);
 LcmCmd(0x06);
 LcmCmd(0x0C); // Display on
 LcmCmd(0x02); // Home

 // CharGen - arrows
 LcmCmd(0x48); // Znak 0x01 na adrese 0x08

// UpArrow
 LcmData(0x04);
 LcmData(0x04);
 LcmData(0x0E);
 LcmData(0x0E);
 LcmData(0x1F);
 LcmData(0x1F);
 LcmData(0x00);
 LcmData(0x00);
//RightArrow
 LcmData(0x10);
 LcmData(0x18);
 LcmData(0x1C);
 LcmData(0x1E);
 LcmData(0x1C);
 LcmData(0x18);
 LcmData(0x10);
 LcmData(0x00);
//LeftArrow
 LcmData(0x01);
 LcmData(0x03);
 LcmData(0x07);
 LcmData(0x0F);
 LcmData(0x07);
 LcmData(0x03);
 LcmData(0x01);
 LcmData(0x00);
//DownArrow
 LcmData(0x00);
 LcmData(0x1F);
 LcmData(0x1F);
 LcmData(0x0E);
 LcmData(0x0E);
 LcmData(0x04);
 LcmData(0x04);
 LcmData(0x00);

 LcmCmd(0x02); // Home
}

void GoToXY(unsigned char X, unsigned char Y) {
 unsigned char B;

 if (Y == 0) {
  B = X;
 }
 else if (Y == 1) {
  B = X + 64;
 }
 else if (Y == 2) {
  B = X + 20;
 }
 else if (Y == 3) {
  B = X + 84;
 }

 B = B | 0x80;
 LcmCmd(B);
}

void CLS(void) {
// Povel 0x01
 LcmCmd(0x01);
}


void Write(unsigned char X, unsigned char Y, unsigned char* Line) {
 unsigned char I = 0,C;

 if (DispDly == 0) {
  GoToXY(X,Y);
  while ((C = (*(Line+I))) != 0) {
   LcmData(C); I++;
  }
 }
}
 

hd44780 lcd user-defined graphics

Ok, I was intrigued by the cgram thing, have never had cause to use it so I grabbed my picdem2 and the latest hitechC + hitide and made this from the examples provided, thanks for bringing this up.
Looking at the datasheet for the ha44780 in more detail there looks to be 3 area's for user definable characters giving a total of 21 :)

written using a pic16f877 control pins porta and data on portd, have added some comments and is without a doubt a mess.

Hope it helps.
 

alphanumeric lcd samples

CAN SOME ONE TELL ME ABT THE DIFFERENCE BETWEEN AT:!:89S51 AND AT89C51
 

alphanumeric lcd custom logo

CGRAM on 44780 is limited to 8 characters, that means you can display atmost 8 user defined characters at one time, but you can change it as often as you want.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top