Custom Character in 16×2 LCD

We have already learned 16×2 LCD interfacing with AVR microcontroller, perform scrolling operation and to print anywhere in LCD. In this post, we will learn about Custom Character Generation in 16×2 LCD.

Before starting to learn about the generation of custom characters, we are going to know a bit more about LCD printing program. For example, what should be the output of particular code?

int main(void)
{
    char b=65;
        while(1)
        {
            LCDGoto(6,0);// 6th on column first row.
            sprintf(a,"%d",b);
            _delay_ms(150);
            LCDdisplay(a);
            sprintf(a,"%c",b);
            LCDGoto(6,1);// 5th on column second row.
            _delay_ms(150);
            LCDdisplay(a);
    }
}

If we execute this program, the output would be ’65’ on top row but in the bottom row, ‘A’ should be there. It’s because of the ASCII(American Standard Code for Information Interchange) value of the ‘A’ is 65. So if we print a “char” type number as a character(%c), we are actually printing an ASCII character having the same ASCII value(ASCII of A=65). Similarly, If we print an ASCII character as a number (%d) the result displayed is the ASCII value of the character.

Custom Character Generation in 16×2 LCD

Before printing the custom characters on LCD, let’s know what we are going to create. I once created a game similar to Google-offline game. In the game, I had created a character- a human. The objective of the game to prevent him from hitting the block coming on his way by jumping over the block. I have to press a button to make it jump over it. Right now, I don’t recommend you to create the game (If you don’t know about interrupt)because I had used the interrupt method for jumping the man. But here we are going to learn how I had created the character and the block for the game so that you can create your own custom characters.

Each block has an address stored in DDRAM. Similarly, each ASCII characters also has an address stored in CGRAM(Character Graphics Random Access Memory). In the CGRAM, there are some locations available for storing the custom characters. We can store maximum 8 custom characters.

So far, you may have noticed that each block of LCD is actually made up of 5 columns and 8 rows. It’s a 5×8 matrix. Each row holds a certain value depends according to the character. For example, I had created a character that looks exactly like me. The numbers for each row comes from the fact that ‘0’ means off and ‘1’ means on. For example- The number for the first line is decided by-xxx01110. ‘x’ means don’t care since it doesn’t matter whatever the value it has after 5 bit because it would not appear on the row. The value on the first row is defined -00001110 means 0E in hexadecimal. Similarly, all the rows have to be defined by you. Note the value down somewhere.

Custom Character in 16x2 LCD

Custom Character in 16x2 LCD

The Program- Custom character in 16×2 LCD

Before going to the program details, I recommend you guys to have an idea about LCD interfacing and It’s basic operations. The program of generating the custom characters is not difficult I would say, but it can be a little hard for beginners. According to the above explanation given, we have to create an array, in which we have to store the numbers you have decided for your own characters. Then we have to store the array into the CGRAM location defined for custom characters(from 40H-7FH) and from there, we are going to assign a character to it’s character code we have given. After that, we can print our custom characters using the character code we have defined. I know, it’s a little difficult to implement but you can understand and implement it. Feel free to ask any query in the comment box.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
char i, b=0x40, c=0x00,z,d,c,f;
const char mycustomchar[] PROGMEM={ 0x0E, 0x11, 0x11, 0x0E, 0x04, 0x04, 0x0A, 0x0A,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };//as in image above
int main(void)
{
char f;
DDRA=0xff;
DDRB=0xff;
cmd(0x01);// Clear the LCD Screen
definechar(mycustomchar,0);// function defined below-it assigns the value to character code. The character code I assign is '0' 
definechar(mycustomchar+8,1);// function defined below-it assigns the value to character code. The character code I assign is '1' 
while(1)
    {
LCDcmd(0x0c);
LCDcmd(0x38);// 2lines 5x7 matrix, 8 bit mode
LCDcmd(0x80);// beginning of first line
LCDGoto(0,1);// 2nd row, first column
sprintf(f,"%c",0);// print 0 as a character
charLCD(f); // print the character
LCDGoto(1,1);// 2nd row 2nd column
sprintf(f,"%c",1);// print '1' as a character
charLCD(f);// print the character
    }
}
void LCDGoto(char x, char y){...}
void LCDcmd(char k){...}
void charLCD(char a){...}
void definechar(const char *pc,char char_code){
char a, pcc;
int i;
a=(char_code<<3)|0x40;
for (i=0; i<8; i++)
    {
pcc=pgm_read_byte(&pc[i]);
LCDcmd(a); a++;
charLCD(pcc);
    }
}

Note that I have not included LCD display, LCD command and LCDGoto in the program. For that, you can refer LCD interfacing with AVR,  and for LCDGoto function refer Print anywhere in LCD

The function define char

The function parameter is a pointer. We know that the name of the array represents the address of it’s [0]th index. The variable ‘a’ stores the address in which we are going to store the character. The address available for storing the “custom character” is from (40H-7FH). Therefore, the first character stores from 40H-47H. Similarly, the second character is from 48H-4FH. If we enter the number from 0 to 7 as a character code, it’s get shifted 3 bits left and then added bitwise to the base number 40H to generate the final address. As in our program, I have defined ‘0’ character code for the man and ‘1’ for the block, the address they are going to stored is-40H-47H and 48H-4FH respectively.

pgm_read_byte(&pc[i]) – function reads a byte from the address passed in the parameter. You don’t need to define the function, it’s right there in the library-avr/pgmspace. You just need to include the header file. The address I pass in the LCDcmd tells the LCD to store the value of custom character array to the particular location. This process assigns the value to the character code you passed. For example, I have passed ‘0’ character code for the man, so whenever I print it with “%c”, I am actually printing the character actually associated with it- the man.

The Modifiers-PROGMEM and CONST

In C language, variable modifiers are the keywords used to change the properties of the current data type. In the program, I have used two variable modifiers-Progmem and Const.The behavior of default variable is not constant. That means you can change the value of the variable anywhere in the program but in the case of the constant variable, you can assign the value but you can’t change it.

TThe PROGMEM keyword is a variable modifier, it should be used only with the datatypes defined in pgmspace.h. It tells the compiler “put this information into flash memory”, instead of into SRAM, where it would normally go.

Execution of the Program

This program executed well both in hardware and simulator-Proteus 8.

 

custom character in LCD

custom character in lcd

 

Leave a Comment

Your email address will not be published. Required fields are marked *

Share This
Scroll to Top