NPEDUCATIONS, Electronic circuits development, electronics tutorials, microcontroller tutorials and projects, advanced microcontroller (ARM) based tutorials and projects, Embedded c development, Embedded c for ARM cortex M, Intel IoT based projects, IoT projects, CC3200 launch pad projects, MSP430 Launchpad tutorials and projects, Tiva C launch pad tutorials and projects, 8051 tutorials and projects, sensor interfacing with microcontroller tutorials, data communications and networking tutorials, peripheral interfacing with microcontroller, led message scrolling display, arduino based tutorials and projects, intel galileo based tutorials and project, ADC interfacing tutorials, LED Blinking, LCD interfacing, Embedded System tutorials and projects, B.tech projects, M.tech projects, online Embedded C training

Custom character generation on 16x2 LCD using 8051 microcontroller


1. Introduction:

In this tutorial, we learn how to create or design custom characters on 16x2 LCD using 8051 microcontroller. Before going to discuss custom characters design on LCD, we will see how the standard characters (which are already stored in LCD memory during manufacture) are displayed on the 16x2 LCD.

2. Displaying standard characters on LCD:

In 16x2 LCD controller HD44780, there are three memory locations are available to store characters, numbers and special symbols.

1.      Display data RAM (DDRAM).
2.      Character Generator ROM (CGROM).
3.      Character Generator RAM (CGRAM). Power failure data loss

Out of these three memory locations, DDRAM and CGROM are used to generate regular standard characters (ASCII characters). By using these three memory locations, a user can generate different character fonts and symbols on LCD display. A character font describes the shape and style of the character. Each shape of a character is designed by taking the number of pixels in mind. For example, in 16x2 LCD there are 16 segments available per single line. Each segment contains pixels in 5x7 or 5x10 matrix forms.

For example, a character in both uppercase ‘A’ and lowercase ‘a’ is designed by making corresponding pixels into black (no light) as shown in figure 1.1,

Figure 1.1 shows the uppercase and lowercase formats of character ‘A’ in 5x7 matrix of LCD display.
 In each row, the ON and OFF pixels of 5x7 matrix is represented by binary values 1 and 0 respectively, from these binary values the hexadecimal code is designed by gathering all 1’s and 0’s as shown in the figure 1.1. All these eight hexadecimal codes (referred as character pattern) of each character are stored in memory. LCD Manufacturers store these hexadecimal representation codes of all ASCII characters in character generator ROM (CGROM) area as shown in figure1.2. We refer the hexadecimal codes in CGROM as standard or basic fonts of characters in LCD.


Figure 1.2 shows Standard ASCII characters stored in CGROM and equivalent ASCII code in hexadecimal is presented as address of that particular character.

The Display Data RAM (DDRAM) stores the ASCII code of a character which is sent by the microcontroller. Now the LCD controller (HD44780) maps the corresponding ASCII code in DDRAM with CGROM address to bring the hexadecimal codes (character pattern) of that particular character. By using those hexadecimal codes the 5x7 matrix segment will light according to that character pattern to display corresponding character on it as shown in figure 1.3.

Figure 1.3 block diagram shows character generation on LCD.

3. Creating and displaying Custom Characters on LCD display:

To create custom characters on LCD, the display controller (HD44780) make use of CGRAM area to store hexadecimal codes (character pattern) which are designed by user. In addition to CGRAM area, DDRAM area is also used to store the CGRAM address of a particular character which is sent by microcontroller in hexadecimal format.

Don’t confuse with the above section of this tutorial “Displaying standard characters on LCD”, in which DDRAM and CGROM memory areas are used to generate regular standard characters. But here, to create and display custom characters on LCD, we use DDRAM and CGRAM (both are RAM’s).

There are only 8 memory locations are available to store user defined characters in CGRAM with address 0x01 (00000001n) – 0x07 (01100001b), which is shown in the figure 1.2 by highlighting locations with green color.


 3.1 Steps to create and display custom character on 16x2 LCD using microcontroller

1.      To create custom characters, first draw a table with 7 rows and 5 columns (5x7 matrix) on a paper. Fill the corresponding squares with some color according to your style of custom character pattern and form the hexadecimal code for each row as shown in figure 1.1.
2.      Initialize LCD with required commands.
3.      Send the Initial address (0x40) of CGRAM as a command to LCD to store the custom character. The next address to store another custom character should be ‘0x48’. That means we should add eight bytes to the present address to get the next address of CGRAM.
4.      Send the all hexadecimal bytes of custom character to CGRAM.
5.      Force the LCD cursor to where you want to display your custom character. If it is beginning of 1st line, then send ‘0x80’ as command.
6.      Send the position of your custom character in CGRAM to LCD.
4. C code to display single custom character program ver1.1:
/**********************************************************************************************************************/
// http://www.npeducations.com
// LCDwithDelay.c - Generating single custom character on 16x2 LCD using 89s52 microcontroller -- program v 1.1
// Author - lovakiranvarma, (M.tech)
// Note: no need provide external delay after command or data, because the send_cmd and send_data functions it self
// provide 1 milliseconds after enable pulse
/**********************************************************************************************************************/
/********************************************** Header Files Declaration **********************************************/
#include
#include
#include
/********************************************* LCD control signals declaration ****************************************/

sbit RS = P2^0;     // Register Select line
sbit RW = P2^1;		// Read/write line
sbit Enable = P2^2;	// Enable line
#define LCD_PORT P0 // define port

/********************************************* LCD function prototypes ************************************************/

void LCD_init(void);
void send_cmd(unsigned char);
void send_char(unsigned char);
void send_String(unsigned char *);
void delayms(unsigned int);
void CustomCharacterStore(void);

/********************************Character array to hold custom character patterns*************************************/
unsigned char CharacterArray[8] = {0x0E,0x11,0x0E,0x04,0x1F,0x04,0x1B,0x00};


/********************************************* Main Funciton declaration **********************************************/

void main()
{

LCD_PORT = 0x00; // Make the port as output port

  	 /****************** Reset process from datasheet **************/
     delayms(15);	// wait for more than 15ms after supply rises to 4.5V
	 send_cmd(0x30);
	 delayms(4);		// wait more than 4.1ms
	 send_cmd(0x30);
	 delayms(1);		// wait more than 100us, but delayms(1) will provide 1ms
	 send_cmd(0x30);
	 delayms(1);
	 send_cmd(0x02); // return to home
	 delayms(1);

  /****************** Initialize LCD **************/		
	LCD_init();				        // LCD initialization
	CustomCharacterStore();

	while(1)
	{
			send_cmd(0x83);  // Force cursor to beginning of 1st line, if the number is 0x83 then force the cursor to 53rd position			
			send_char(0x00); // locate the first character in CGRAM
	}
	

}

void CustomCharacterStore()
{
	unsigned char i=0,j=0;
		send_cmd(0x40);       //Load the location where we want to store
		
		/**Store the custom character pattern in CGRAM area**/
        send_char(0x0E);      //Load row 1 data
	    send_char(0x11);      //Load row 2 data
	    send_char(0x0E);      //Load row 3 data
	    send_char(0x04);      //Load row 4 data
	    send_char(0x1F);      //Load row 5 data
	    send_char(0x04);      //Load row 6 data
		send_char(0x1B);      //Load row 7 data
		send_char(0x00);      //Load row 8 data, this 8th won't display on LCD, because the matrix is 5x7
}

/********************************************* LCD Initialization Function declaration ********************************/

void LCD_init()
{
	send_cmd(0x38);  					// configuring LCD as 2 line 5x7 matrix in 8-bit mode
	send_cmd(0x0C);  					// Display on, Cursor blinking
	send_cmd(0x01);  					// Clear Display Screen
	send_cmd(0x06);  					// Increment Cursor (Right side)
}

/******************************************* LCD single character sending Function declaration************************************/

void send_char(unsigned char character)
{
	LCD_PORT = character;
	RS = 1;				// Select Data Register
	RW = 0;				// write operation
	Enable = 1;		    // High to Low pulse provided on the enable pin with nearly 1ms(>450ns)
	delayms(1);			// 1 millisec delay
	Enable = 0;
	delayms(1);			// 1 millisec delay
}


/*********************************************LCD Command Sending Function declaration********************************/

void send_cmd(unsigned char Command)
{
	LCD_PORT = Command;
	RS = 0;		  		// Select Command Register
	RW = 0;				// write operation
	Enable = 1;		    // High to Low pulse provided on the enable pin with nearly 1ms(>450ns)
	delayms(1);			// 1 millisec delay
	Enable = 0;
	delayms(1);			// 1 millisec delay

}
/******************************************* LCD String sending Function declaration*************************************/

void send_String(unsigned char *String)
{
unsigned char i=0;

	while(String[i]!='\0')
	{
				 
		LCD_PORT = String[i++];
		RS = 1;			 // Select Data Register
		RW = 0;			 // write operation
		Enable = 1;		 // High to Low pulse provided on the enable pin with nearly 1ms(>450ns)
		delayms(1);		 // 1 millisec delay
		Enable = 0;
		delayms(1);		 // 1 millisec delay
		if(i>=16)		 // If the number of characters in the string > 16, then the below command automatically 
		send_cmd(0x1C);	 // Shift the display right side 
		delayms(100);	 // 100 millisec delay
	}
	
}

/******************************************* delayms Function declaration***********************************************/
void delayms(unsigned int value)
{
	unsigned int i,j;
		
	for(i=0;i<=value;i++)
	{
		for(j=0;j<100;j++)
		_nop_();		 // no operation produce 1us time delay
	}
	
}


4.1 Output in proteus software for the program1.1:

Figure 1.4 displaying animated boy on LCD using proteus simulation software






5. C code to display more than one custom character using pointers:

In this code I have the changed CustomCharacterStore() function, which is allowed to store 1 to 8 custom characters in CGRAM with the help of pointers concept in C language. And I have created a two dimensional array to define custom character patterns and in the main function, each character is called separately using send_char() function.

5.1 C code to display eight custom characters – program ver1.2:
/***************************************************************************************************************************/
// http://www.npeducations.com
// LCDwithDelay.c - Generation of custom characters on 16x2 LCD using 89s52 microcontroller
// Author - lovakiranvarma, (M.tech)
// Note: no need provide external delay after command or data, because the send_cmd and send_data functions it self
// provide 1 milliseconds after enable pulse
/***************************************************************************************************************************/
/********************************************** Header Files Declaration ***************************************************/
#include
#include
#include
/********************************************* LCD control signals declaration ***************************************************/

sbit RS = P2^0;     // Register Select line
sbit RW = P2^1;		// Read/write line
sbit Enable = P2^2;	// Enable line
#define LCD_PORT P0 // define port

/********************************************* LCD function prototypes ************************************************/

void LCD_init(void);
void send_cmd(unsigned char);
void send_String(unsigned char*);
void send_char(unsigned char);
void delayms(unsigned int);
void CustomCharacterStore(void);

/********************************Character array to hold custom character patterns*************************************/
unsigned char CharacterArray[8][8] = {{0x0E,0x11,0x0E,0x04,0x1F,0x04,0x1B,0x00}, // boy
									  {0x00,0x00,0x1E,0x13,0x13,0x0C,0x1F,0x00},	// cup
									  {0x00,0x0A,0x0A,0x00,0x11,0x0E,0x06,0x00},	// simley
									  {0x00,0x00,0x1B,0x1F,0x0E,0x04,0x00,0x00}, // love
									  {0x00,0x19,0x1A,0x04,0x0B,0x13,0x00,0x00}, // percentage
									  {0x1F,0x11,0x0A,0x04,0x0A,0x15,0x1F,0x00}, // hour glass
									  {0x00,0x1B,0x15,0x11,0x11,0x1F,0x00,0x00},// mail folder
									  {0x00, 0x0E, 0x11, 0x1F, 0x15, 0x1F, 0x0A}}; // android robo


/********************************************* Main Funciton declaration ***********************************************/

void main()
{

LCD_PORT = 0x00; // Make the port as output port

  	 /****************** Reset process from datasheet **************/
     delayms(15);	// wait for more than 15ms after supply rises to 4.5V
	 send_cmd(0x30);
	 delayms(4);		// wait more than 4.1ms
	 send_cmd(0x30);
	 delayms(1);		// wait more than 100us, but delayms(1) will provide 1ms
	 send_cmd(0x30);
	 delayms(1);
	 send_cmd(0x02); // return to home
	 delayms(1);

  /****************** Initialize LCD **************/		
	LCD_init();				        // LCD initialization
	CustomCharacterStore();

	while(1)
	{
			send_cmd(0x80);  // Force cursor to beginning of 1st line, if the number is 0x83 then force the cursor to 53rd position			
			send_char(0x00); // locate the first character in CGRAM
			send_char(' ');  // space
			send_char(0x01); // locate the second character in CGRAM
			send_char(' ');  // space
			send_char(0x02); // locate the third character in CGRAM
			send_char(' ');  // space
			send_char(0x03); // locate the fourth character in CGRAM
			send_char(' ');  // space
			send_char(0x04); // locate the fifth character in CGRAM
			send_char(' ');  // space
			send_char(0x05); // locate the sixth character in CGRAM
			send_char(' ');  // space
			send_char(0x06); // locate the seventh character in CGRAM
			send_char(' ');  // space
			send_char(0x07); // locate the eigth character in CGRAM		
			send_char(' ');  // space
			
	

}

void CustomCharacterStore()
{
unsigned char i=0,j=0;
		//send_cmd(0x48);       //Load the location where we want to store
		//delayms(1);				// Delay of 1millisec

		/**Store the custom character patterns in CGRAM area**/
											     
		while(j<8)
		{
			send_cmd(0x40 + (j*8));
				for(i=0;i<8;i++)
				{
					send_char(CharacterArray[j][i]);
				}
				j++;
		}
	
}

/********************************************* LCD Initialization Function declaration ********************************/

void LCD_init()
{
	send_cmd(0x38);  					// configuring LCD as 2 line 5x7 matrix in 8-bit mode
	send_cmd(0x0C);  					// Display on, Cursor blinking
	send_cmd(0x01);  					// Clear Display Screen
	send_cmd(0x06);  					// Increment Cursor (Right side)
}

void send_char(unsigned char character)
{
	LCD_PORT = character;
	RS = 1;				// Select Data Register
	RW = 0;				// write operation
	Enable = 1;		    // High to Low pulse provided on the enable pin with nearly 1ms(>450ns)
	delayms(1);			// 1 millisec delay
	Enable = 0;
	delayms(1);			// 1 millisec delay
}


/*********************************************LCD Command Sending Function declaration********************************/

void send_cmd(unsigned char Command)
{
	LCD_PORT = Command;
	RS = 0;		  		// Select Command Register
	RW = 0;				// write operation
	Enable = 1;		    // High to Low pulse provided on the enable pin with nearly 1ms(>450ns)
	delayms(1);			// 1 millisec delay
	Enable = 0;
	delayms(1);			// 1 millisec delay
}

/******************************************* delayms Function declaration***********************************************/
void delayms(unsigned int value)
{
	unsigned int i,j;
		
	for(i=0;i<=value;i++)
	{
		for(j=0;j<100;j++)
		_nop_();		 // no operation produce 1us time delay
	}
	
}



5.2 Output in proteus software for program 1.2

Figure 1.5 displaying different animated custom characters on LCD using proteus simulation software.


4 comments :

  1. how to store more than 8 custom character...please can you tell me?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. @Amit Dubey you can't store more than 8 characters at a time. But you can display more than 8 custom characters easily by modifying the CharacterArray

    ReplyDelete
  4. You should also check The Engineering Projects because they have posted a lot of Arduino Projects and PIC Mirocontroller Projects and have also designed many new Proteus Tutorials. I hope you guys are gonna like them.

    ReplyDelete

Thanks for visiting NPEDUCATIONS. We will contact you soon

4 comments :

Amit Dubey said...

how to store more than 8 custom character...please can you tell me?

Abdul-Rauf said...
This comment has been removed by the author.
Abdul-Rauf said...

@Amit Dubey you can't store more than 8 characters at a time. But you can display more than 8 custom characters easily by modifying the CharacterArray

Syed Zain Nasir said...

You should also check The Engineering Projects because they have posted a lot of Arduino Projects and PIC Mirocontroller Projects and have also designed many new Proteus Tutorials. I hope you guys are gonna like them.

Post a Comment

Thanks for visiting NPEDUCATIONS. We will contact you soon

If you really like this tutorial, Don't forget to give the comment or please subscribe to the RSS feed by submitting your E-mail or like our Facebook page.
Related Posts Plugin for WordPress, Blogger...

 
Powered by Blogger