Saturday, November 26, 2011

§ Interfacing HD44780 LCD – Part2

Hello Friends,

In my previous post I cover the introduction part of HITACHI 16x2 character LCD. In this post I will explain you its internal operation that how a character prints on LCD screen. To understand its internal operation we have to know about these terms-

            IR:  Instruction register
            DR: Data Register
            AC: Address Counter
            DDRAM: Display Data RAM
            CGROM: Character Generator ROM
            CGRAM: Character Generator RAM

Let’s understand these terms one by one. As I told you in the previous post that HD44780 has two 8-bit registers—
1.      Instruction Register : IR
2.      Data Register : DR

IR stores instruction codes such as display clear, cursor position, font size etc. HD44780 Datasheet provides a Command Sets for LCD to do these things. We just put the command code in IR to perform the task which we want. In this post I will also explain you that how to use these command sets.

MCU send data to LCDs data pins. How LCD recognize that the data coming from MCU is an ASCII character or it’s a command?? Answer depends on the status of RS pin.

If RS=”0” then data coming from MCU is stored in IR. LCD treats this data as an instruction or command.

If RS=”1” then data coming from MCU is stored in DR. LCD treats this data as a character.

DR is used for storing data (ascii value of a character) which is ready to be displayed on LCD. When ENABLE pin of LCD is set to “1” (HIGH), the data coming from MCU is latched inside IR or DR depends on the status of RS pin. If RS=”1” then data is latched into DR and moved automatically into DDRAM or CGRAM by an internal operation and displayed on LCD screen. See the timing diagram below for more clarification.

 
AC: When we store data into instruction register then basically we are storing the location (address) of that instruction/command. This address information is now sent from IR to AC. After writing into DDRAM or CGRAM, the AC is automatically incremented by one.


DDRAM:  
Display data RAM (DDRAM) stores display data represented in 8-bit character codes. Its extended capacity is 80 X 8 bits, or 80 characters. The area in display data RAM (DDRAM) that is not used for display can be used as general data RAM. 

Basically DDRAM provides the location (address) to the character where it will be displayed on LCD screen. To print any character we have to set DDRAM address first and then we have to send the ascii/Hex value of that character. Because our LCD size is 16x2 hence only 16 characters in one line is visible, total of 32 characters we can display at a time on the screen.

 
CGROM:
The bitmap images of all the characters are previously stored in Character Generator ROM. DDRAM fetch bitmap image of the character from this ROM. It generates 5x8 dot or 5x10 dot character patterns from 8-bit character code (ascii code or Hex code).See Figure below :

 

CGRAM can generate 208, 5x8 dot character patterns and 32, 5x10 dot character patterns. In the above figure green area shows CGRAM area.

CGRAM:
If we want to display some special characters then CGRAM is used; it is located at 0x00 to 0x07(Highlighted green in the figure). You can design your custom characters and displays on LCD. I will post on ‘custom character designing’ separately in next post.

Block Diagram from above discussion:




Writing Data and Commands: 
I am using LCD in 4-bit mode means its only 4 data pins (MSB) is used to send data. Because our microcontroller deals with 8-bit data, so we have to send data to LCD in two parts. First we have to send MSB and then LSB. To do this we have to first mask MSB of the data and send to LCD then we have to shift this data 4 times Left due to this LSB comes in place of MSB position and then send it to LCD.

Send Character to LCD: In order to print a character onto LCD we have to select data register first means RS=”1”. And we know that data is processed only when EN=”1” one more thing is to be remember that EN should low before sending data or command. OK! These  information is enough to print a character.Follow this algorithm to do this :

Step: 1 Put MSB of the data on LCD data pins
Step: 2 EN = 0; RS=1 
Step: 3 EN=1  wait  EN=0   (Clock to latch MSB)
Step: 4 put LSB of the data
Step: 5 EN = 0; RS=1
Step: 6 EN=1  wait  EN=0   (Clock to latch LSB)
Step: 7 Wait

Function to Send Character to LCD:  I write the program in ‘C’ for AVR microcontroller. Here I only show you the function used to display a character. You will get complete code and macro definition in my next post.

void Send_LCD_Char(uint8_t data)
{
   LCD_PORT=(data & 0xF0);         //MSB
   SET_RS;
   Clock();

   LCD_PORT=((data & 0x0F) << 4);  //LSB
   SET_RS;
   Clock();
  _delay_ms(5);                    //wait (LCD is busy)
}

Example : Send_LCD_Char(‘A’);

Send Command to LCD:  Only RS will change, other things remain unchanged. For command mode RS=0.Algorithm:

Step: 1 Put MSB of the data
Step: 2 EN = 0; RS=0
Step: 3 EN=1  wait  EN=0   (Clock to latch MSB)
Step: 4 put LSB of the data
Step: 5 EN = 0; RS=0
Step: 6 EN=1  wait  EN=0   (Clock to latch LSB)
Step: 7 Wait

Function to Send Command to LCD:
void Send_LCD_Cmd(uint8_t data)
{
   LCD_PORT=(data & 0xF0);         //MSB
   RESET_RS;
   Clock();
     
   LCD_PORT=((data & 0x0F) << 4);  //LSB
   RESET_RS;
   Clock();
  _delay_ms(5);                    // Wait (LCD is busy)
 
}
Example : Send_LCD_Cmd(0x01);


Busy Flag (BF): There is one more thing which I want to explain shortly. You will notice that in both of the function at the end of function I write some delay. This delay is needed for LCD to successfully process the data.

We can set the accurate delay required by the LCD to process  the data using Busy Flag reading function.To access the busy flag we have to use RW pin because we have to read the status of busy flag from LCD. When BF=1, means LCD is processing a command/data or we can say that LCD is busy till BF=1. When LCD is busy it will not accepts any command/data. So we have to poll (Read) busy Flag to ensure that BF=0. When BF=0 LCD is ready to process next data.

The only advantage to use BF is that it will give exact amount of time which LCD needs to process the data. However, Busy Flag reading may be ignored by simply using delay function so I write this delay in code and that’s the region why I grounded RW pin.

LCD Command Sets: HD44780 Datasheet provides a table for LCD commands which is very useful during writing code for LCD.


Some Useful Commands:
0x01 -  LCD Clear
0x0C – Turn on LCD, No cursor
0x0E – Solid Cursor
0x0F – Blinking Cursor
0x80 -  Moves cursor to first address on the left of LINE 1
0xC0 - Moves cursor to first address on the left of LINE 2
0x1C – Shift display right
0x18 – Shift display left
0x28 – 4-Bit mode, 2-line, 5x7 Font
0x06 – Automatic increment in cursor, no display shift

LCD Initialization:
LCD initialization is just a set of commands which prepare the LCD according to our requirement. To use LCD we first have to initialize it at the beginning of the main program.
We can Initialize LCD using two methods: 1. Using Internal Reset 2.Using Software 

I found in datasheet that internal initialization is set for 8-bit mode, which is not useful because we are using 4-bit mode so we have to write a function to initialize it with our requirements. HD44780 Datasheet gives a flowchart for initialization.

 

Function For LCD Initialization: According to this algorithm we can easily write code for LCD initialization.

void LCD_init()
{
  _delay_ms(20);

  LCD_DDR = 0xFF;
  LCD_PORT = 0x00;

  Send_LCD_Cmd(0x30);
  _delay_ms(5);

  Send_LCD_Cmd(0x30);
  _delay_us(200);

  Send_LCD_Cmd(0x30);
  _delay_us(200);

  Send_LCD_Cmd(0x28); //4-bit mode, 2-line - 5x7 Font
  Send_LCD_Cmd(0x06); //Auto. Increment - NO disp. shift
  Send_LCD_Cmd(0x01); //clear display
  Send_LCD_Cmd(0x0C); //NO cursor - NO Blink
}


Ok!! Now all things done!! In the next post I will show you How to work with LCD and its Interfacing with AVR Microcontroller and doing some practical stuff.


                                                                                                                                               ~Pratyush
                                                                                                                          

No comments:

Post a Comment

PID Controlled Self balancing Robot using ESP8266 and MPU6050

This ROBOT is made using ESP8266 Node MCU and MPU6050 accelerometer. Motor used here is normal gear motor of 150 rpm with TB6612FNG motor dr...