Display custom urdu language characters on 16×2 lcd using pic16f877a microcontroller

In this project i am going to display urdu language characters on 16×2 lcd using pic16f877 microcontroller. Urdu is a language spoken in Pakistan, India and Bangladesh. Character lcd’s generally contains a Hitachi HD4478 controller in it. Hd4478 only contains ASCII character set in it and we can only display the predefined characters that are present in it. It contains numeric, English and Chinese language characters in it.
So to display urdu characters we must know about how to make custom characters and display it on character 16×2 lcd. Displaying self made custom characters on lcd requires knowledge about internal structure of lcd. To display custom characters like urdu you should know about lcd CG-RAM,data & command registers.

Display custom urdu language characters on 16×2 lcd using pic16f877a microcontroller

A good and perfect tutorial to understand the internal structure of lcd CG(character generated) ram is given below. Since its very important and lengthy topic so it is not possible to explain it here. I recommend you to please take the below tutorial other wise you will be unable to understand the project code below. 

How to generate custom characters in cg ram of 16×2 character lcd. 

Project Requirements
  • Pic 16f877 microcontroller
  • 16×2 lcd
  • Crystal 20 MHz
  • Potentiometer (For setting lcd Contrast)
Lcd is interfaced with Pic16f877 microcontroller in 8-bit mode. Lcd data pins are directly connected to Port-B of Pic16f877 microcontroller. Lcd control signals rw(read-write) rs(register select) and en(enable) are provided by Port-D pins RD5,RD6 and RD7 of Pic16f877 microcontroler. The circuit diagram of the project is given below.
 
Coming to the code portion. The code is written in c language using MP-lab ide. High tech c compiler is used to compile the code. Header file htc.h is imported first. This file is must to be included in every project that is using high tech c compiler for compiling the code. Then crystal frequency is defined which is 20 MHz(20e6=20^6). Lcd control pins are defined next. Then the delay() function is defined which is generating some arbitrary delay for us. lcdcmd() function is sending commands to command register of lcd. dispaly() function is sending data to data register of lcd. If you dont know about lcd data and command register and their working here is a good tutorial.
Lcdint() function is initializing our lcd. The tutorial given a line above also covers the lcd intialization phase and intializing commands. In the main fuction i am generating urdu alphabets in CG-RAM and then they are diaplayed on 16×2 lcd. First i give command lcdcmd(0x40) to lcd. This 0x40 is the starting address of CG-RAM. Then the individual dots of urdu first character “i” is send to lcd. Next 0x48 is send to lcd. Which is the second address of CG-RAM character. Second character dots are then send to CG-RAM of lcd. This process repeats for the eight characters. Then all the eight custom generated characters are invoked for displaying on lcd by just giving their address(0 to 8).
After displaying first eight urdu characters next eight are build in CG-RAM and then displayed on lcd. This process repeats until the last character is displayed. After last character the lcd starts from beginning and starts displaying urdu characters from beginning. 

Note: Lcd first line continuously display “Urdu Characters!” and the urdu characters are displayed on the second line. Each urdu character is displayed on lcd with one matrix gap from other. Since 16×2 lcd has 16 coulombs so 8 characters with one matrix sepration from others are perfectly displayed on the lcd second line.

 

//***********************************************
//Property off: www.microcontroller-project.com *
//Written by : Usman Ali Butt *
//Date : 19/5/2015 *
//***********************************************
#include
#define __XTAL_FREQ 20e6
#define en RD7
#define rs RD6
#define rw RD5

void delay(unsigned int time) //Time delay function
{
unsigned int i,j;
for(i=0;i< time;i++)
for(j=0;j< 30;j++);
}

//Function for sending values to the command register of LCD
void lcdcmd(unsigned char value)
{
PORTB=value;
rs= 0; //register select-rs
rw = 0; //read-write-rd
en = 1; //enable-e
delay(50);
en=0; //enable-e
delay(50);

}
//Function for sending values to the data register of LCD
void display(unsigned char value)
{
PORTB=value;
rs= 1; //register select-rs
rw= 0; //read-write-rd
en= 1; //enable-e
delay(500);
en=0; //enable-e
delay(50);

}
//function to initialize the registers and pins of LCD
//always use with every lcd of hitachi
void lcdint(void)
{
TRISB=0x00; //Port 1 is used as output port
TRISD5=0; //Lcd Controlling pins
TRISD6=0; //Lcd Controlling pins
TRISD7=0; //Lcd Controlling pins
delay(15000);
display(0x30);
delay(4500);
display(0x30);
delay(300);
display(0x30);
delay(650);
lcdcmd(0x38);
delay(50);
lcdcmd(0x0C);
delay(50);
lcdcmd(0x01);
delay(50);
lcdcmd(0x06);
delay(50);
lcdcmd(0x80);
delay(50);
}

void main()
{
int i;
lcdint();

while(1){
lcdcmd(0x01);
i=0;
char line1[]={“Urdu Characters!”};
while(line1[i]!=’\0′)
{
display(line1[i]);
i++;
}
delay(10000);

lcdcmd(0x40); //CG-RAM first address
display(0x02);display(0x04);display(0x04);display(0x04);display(0x04);display(0x04);display(0x08);
lcdcmd(0x40+8); //CG-RAM second address
display(0x00);display(0x00);display(0x00);display(0x11);display(0x0E);display(0X00);display(0X04);
lcdcmd(0x40+16);
display(0x00);display(0x00);display(0X11);display(0X0E);display(0x00);display(0X0A);display(0X04);
lcdcmd(0x40+24);
display(0x00);display(0x0A);display(0x00);display(0x11);display(0x0E);display(0x00);display(0x00);
lcdcmd(0x40+32);
display(0x04);display(0x06);display(0x06);display(0x00);display(0x11);display(0x0E);display(0x00);
lcdcmd(0x40+40);
display(0x00);display(0x0A);display(0x04);display(0x11);display(0x0E);display(0x00);display(0x00);
lcdcmd(0x40+48);
display(0x1F);display(0x12);display(0x14);display(0x08);display(0x14);display(0x11);display(0x04);
lcdcmd(0x40+56);
display(0x1F);display(0x12);display(0x14);display(0x08);display(0x16);display(0x15);display(0x04);

delay(5000);
lcdcmd(0xC0);//Jump to secod line of 16×2 lcd
display(0); //Display first character on lcd.
lcdcmd(0xC2);//Jump to second line third Matrix
display(1); //Display Second Character on lcd.
lcdcmd(0xC4);//Jump to second line fifth Matrix.
display(2); //Display third character on lcd.
lcdcmd(0xC6);
display(3);
lcdcmd(0xC8);
display(4);
lcdcmd(0xCA);
display(5);
lcdcmd(0xCC);
display(6);
lcdcmd(0xCE);
display(7);

delay(100000); //Wait for some time
delay(100000);

lcdcmd(0x40);
display(0x1F);display(0x12);display(0x14);display(0x08);display(0x10);display(0x12);display(0x1E);
lcdcmd(0x40+8);
display(0x04);display(0x1F);display(0x12);display(0x08);display(0x10);display(0x12);display(0x1E);
lcdcmd(0x40+16);
display(0x00);display(0x06);display(0x09);display(0x11);display(0x01);display(0x12);display(0x0c);
lcdcmd(0x40+24);
display(0x08);display(0x06);display(0x09);display(0x11);display(0x01);display(0x12);display(0x0c);
lcdcmd(0x40+32);
display(0x00);display(0x08);display(0x04);display(0x02);display(0x02);display(0x04);display(0x08);
lcdcmd(0x40+40);
display(0x04);display(0x08);display(0x04);display(0x02);display(0x02);display(0x04);display(0x08);
lcdcmd(0x40+48);
display(0x15);display(0x1F);display(0x08);display(0x07);display(0x11);display(0x0E);display(0x00);
lcdcmd(0x40+56);
display(0x04);display(0x0A);display(0x15);display(0x1F);display(0x08);
display(0x07);display(0x11);display(0x0E);

delay(5000);
lcdcmd(0xC0);
display(0);
lcdcmd(0xC2);
display(1);
lcdcmd(0xC4);
display(2);
lcdcmd(0xC6);
display(3);
lcdcmd(0xC8);
display(4);
lcdcmd(0xCA);
display(5);
lcdcmd(0xCC);
display(6);
lcdcmd(0xCE);
display(7);

delay(100000);
delay(100000);

lcdcmd(0x40);
display(0x00);display(0x07);display(0x05);display(0x17);display(0x14);display(0x14);display(0x08);
lcdcmd(0x40+8);
display(0x02);display(0x07);display(0x05);display(0x17);display(0x14);display(0x14);display(0x08);
lcdcmd(0x40+16);
display(0x10);display(0x10);display(0x11);display(0x13);display(0x15);display(0x19);display(0x1E);
lcdcmd(0x40+24);
display(0x10);display(0x10);display(0x15);display(0x13);display(0x15);display(0x19);display(0x1E);
lcdcmd(0x40+32);
display(0x04);display(0x08);display(0x04);display(0x08);display(0x10);display(0x11),display(0x0E);
lcdcmd(0x40+40);
display(0x08);display(0x04);display(0x08);display(0x04);display(0x08);display(0x11);display(0x0E);
lcdcmd(0x40+48);
display(0x00);display(0x02);display(0x05);display(0x0A);display(0x04);display(0x11);display(0x0E);
lcdcmd(0x40+56);
display(0x00);display(0x00);display(0x01);display(0x02);display(0x04);display(0x11);display(0x0E);

delay(5000);
lcdcmd(0xC0);
display(0);
lcdcmd(0xC2);
display(1);
lcdcmd(0xC4);
display(2);
lcdcmd(0xC6);
display(3);
lcdcmd(0xC8);
display(4);
lcdcmd(0xCA);
display(5);
lcdcmd(0xCC);
display(6);
lcdcmd(0xCE);
display(7);

delay(100000);
delay(100000);

lcdcmd(0x40);
display(0x01);display(0x01);display(0x01);display(0x01);display(0x11);display(0x11);display(0x0E);
lcdcmd(0x40+8);
display(0x1F);display(0x15);display(0x17);display(0x10);display(0x10);display(0x10);display(0x10);
lcdcmd(0x40+16);
display(0x11);display(0x11);display(0x15);display(0x11);display(0x0A);display(0x00);display(0x00);
lcdcmd(0x40+24);
display(0x04);display(0x0A);display(0x15);display(0x15);display(0x08);display(0x10);display(0x00);
lcdcmd(0x40+32);
display(0x02);display(0x05);display(0x04);display(0x03);display(0x11);display(0x11);display(0x0E);
lcdcmd(0x40+40);
display(0x00);display(0x00);display(0x01);display(0x1F);display(0x10);display(0x1F);display(0x00);

delay(5000);
lcdcmd(0xC0);
display(‘ ‘);
lcdcmd(0xC2);
display(0);
lcdcmd(0xC4);
display(1);
lcdcmd(0xC6);
display(2);
lcdcmd(0xC8);
display(3);
lcdcmd(0xCA);
display(4);
lcdcmd(0xCC);
display(5);
lcdcmd(0xCE);
display(‘ ‘);
delay(10000);
delay(10000);
}
}

About The Author

Muhammad Bilal

I am a highly skilled and motivated individual with a Master's degree in Computer Science. I have extensive experience in technical writing and a deep understanding of SEO practices.