lcd interfacing with microcontrollers tutorial

Upload: shashank-raju

Post on 05-Apr-2018

234 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    1/31

    LCD interfacing with Microcontrollers tutorial

    IntroductionThe most commonly used Character based LCDs are based on Hitachi's HD44780controller or other which are compatible with HD44580. In this tutorial, we will discuss

    about character based LCDs, their interfacing with various microcontrollers, variousinterfaces (8-bit/4-bit), programming, special stuff and tricks you can do with these

    simple looking LCDs which can give a new look to your application.

    For Specs and technical information HD44780 controller Click Here

    Pin DescriptionThe most commonly used LCDs found in the market today are 1 Line, 2 Line or 4 Line

    LCDs which have only 1 controller and support at most of 80 charachers, whereas LCDssupporting more than 80 characters make use of 2 HD44780 controllers.

    Most LCDs with 1 controller has 14 Pins and LCDs with 2 controller has 16 Pins (twopins are extra in both for back-light LED connections). Pin description is shown in the

    table below.

    Figure 1: Character LCD type HD44780 Pin diagram

    Pin No. Name Description

    Pin no. 1 VSS Power supply (GND)

    Pin no. 2 VCC Power supply (+5V)

    Pin no. 3 VEE Contrast adjust

    Pin no. 4 RS0 = Instruction input

    1 = Data input

    Pin no. 5 R/W 0 = Write to LCD module

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    2/31

    1 = Read from LCD module

    Pin no. 6 EN Enable signal

    Pin no. 7 D0 Data bus line 0 (LSB)

    Pin no. 8 D1 Data bus line 1

    Pin no. 9 D2 Data bus line 2Pin no. 10 D3 Data bus line 3

    Pin no. 11 D4 Data bus line 4

    Pin no. 12 D5 Data bus line 5

    Pin no. 13 D6 Data bus line 6

    Pin no. 14 D7 Data bus line 7 (MSB)

    Table 1: Character LCD pins with 1 Control ler

    Pin No. Name Description

    Pin no. 1 D7 Data bus line 7 (MSB)

    Pin no. 2 D6 Data bus line 6

    Pin no. 3 D5 Data bus line 5

    Pin no. 4 D4 Data bus line 4

    Pin no. 5 D3 Data bus line 3

    Pin no. 6 D2 Data bus line 2

    Pin no. 7 D1 Data bus line 1

    Pin no. 8 D0 Data bus line 0 (LSB)

    Pin no. 9 EN1 Enable signal for row 0 and 1 (1stcontroller)

    Pin no. 10 R/W 0 = Write to LCD module1 = Read from LCD module

    Pin no. 11 RS0 = Instruction input

    1 = Data input

    Pin no. 12 VEE Contrast adjust

    Pin no. 13 VSS Power supply (GND)

    Pin no. 14 VCC Power supply (+5V)

    Pin no. 15 EN2 Enable signal for row 2 and 3 (2nd

    controller)

    Pin no. 16 NC Not Connected

    Table 2: Character LCD pins with 2 Control ler

    Usually these days you will find single controller LCD modules are used more in the

    market. So in the tutorial we will discuss more about the single controller LCD, theoperation and everything else is same for the double controller too. Lets take a look at the

    basic information which is there in every LCD.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    3/31

    DDRAM - Display Data RAM

    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. So whatever

    you send on the DDRAM is actually displayed on the LCD. For LCDs like 1x16, only 16characters are visible, so whatever you write after 16 chars is written in DDRAM but is

    not visible to the user.

    Figures below will show you the DDRAM addresses of 1 Line, 2 Line and 4 Line LCDs.

    Figure 2: DDRAM Address for 1 Line LCD

    Figure 3: DDRAM Address for 2 Line LCD

    Figure 4: DDRAM Address for 4 Line LCD

    CGROM - Character Generator ROMNow you might be thinking that when you send an ascii value to DDRAM, how the

    character is displayed on LCD? so the answer is CGROM. The character generator ROMgenerates 5 x 8 dot or 5 x 10 dot character patterns from 8-bit character codes (see Figure

    5 and Figure 6 for more details). It can generate 208 5 x 8 dot character patterns and 32 5x 10 dot character patterns. Userdefined character patterns are also available by mask-

    programmed ROM.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    4/31

    Figure 5: LCD characters code map for 5x8 dots

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    5/31

    Figure 6: LCD characters code map for 5x10 dots

    As you can see in both the code maps, the character code from 0x00 to 0x07 is occupiedby the CGRAM characters or the user defined characters. If user want to display the

    fourth custom character then the code to display it is 0x03 i.e. when user send 0x03 codeto the LCD DDRAM then the fourth user created charater or patteren will be displayed

    on the LCD.

    CGRAM - Character Generator RAMAs clear from the name, CGRAM area is used to create custom characters in LCD. In the

    character generator RAM, the user can rewrite character patterns by program. For 5 x 8dots, eight character patterns can be written, and for 5 x 10 dots, four character patterns

    can be written. Later in this tutorial i will explain how to use CGRAM area to makecustom character and also making animations to give nice effects to your application.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    6/31

    BF - Busy FlagBusy Flag is an status indicator flag for LCD. When we send a command or data to the

    LCD for processing, this flag is set (i.e BF =1) and as soon as the instruction is executedsuccessfully this flag is cleared (BF = 0). This is helpful in producing and exact ammount

    of delay. for the LCD processing.

    To read Busy Flag, the condition RS = 0 and R/W = 1 must be met and The MSB of theLCD data bus (D7) act as busy flag. When BF = 1 means LCD is busy and will not

    accept next command or data and BF = 0 means LCD is ready for the next command ordata to process.

    Instruction Register (IR) and Data Register (DR)There are two 8-bit registers in HD44780 controller Instruction and Data register.

    Instruction register corresponds to the register where you send commands to LCD e.gLCD shift command, LCD clear, LCD address etc. and Data register is used for storingdata which is to be displayed on LCD. when send the enable signal of the LCD is

    asserted, the data on the pins is latched in to the data register and data is then movedautomatically to the DDRAM and hence is displayed on the LCD.

    Data Register is not only used for sending data to DDRAM but also for CGRAM, theaddress where you want to send the data, is decided by the instruction you send to LCD.

    We will discuss more on LCD instuction set further in this tutorial.

    Commands and Instruction setOnly the instruction register (IR) and the data register (DR) of the LCD can be controlledby the MCU. Before starting the internal operation of the LCD, control information is

    temporarily stored into these registers to allow interfacing with various MCUs, whichoperate at different speeds, or various peripheral control devices. The internal operation

    of the LCD is determined by signals sent from the MCU. These signals, which includeregister selection signal (RS), read/write signal (R/W), and the data bus (DB0 to DB7),

    make up the LCD instructions (Table 3). There are four categories of instructions that:

    Designate LCD functions, such as display format, data length, etc.

    Set internal RAM addresses

    Perform data transfer with internal RAM

    Perform miscellaneous functions

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    7/31

    Table 3: Command and Instruction set for LCD type HD44780

    Although looking at the table you can make your own commands and test them. Below is

    a breif list of useful commands which are used frequently while working on the LCD.

    No.Instruction Hex Decimal

    1 Function Set: 8-bit, 1 Line, 5x7 Dots 0x30 48

    2 Function Set: 8-bit, 2 Line, 5x7 Dots 0x38 56

    3 Function Set: 4-bit, 1 Line, 5x7 Dots 0x20 32

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    8/31

    4 Function Set: 4-bit, 2 Line, 5x7 Dots 0x28 40

    5 Entry Mode 0x06 6

    6

    Display off Cursor off

    (clearing display without clearing DDRAMcontent)

    0x08 8

    7 Display on Cursor on 0x0E 14

    8 Display on Cursor off 0x0C 12

    9 Display on Cursor blinking 0x0F 15

    10 Shift entire display left 0x18 24

    12 Shift entire display right 0x1C 30

    13 Move cursor left by one character 0x10 16

    14 Move cursor right by one character 0x14 20

    15 Clear Display (also clear DDRAM content) 0x01 1

    16

    Set DDRAM address or coursor position on

    display 0x80+add* 128+add*

    17Set CGRAM address or set pointer toCGRAM location

    0x40+add** 64+add**

    Table 4: Frequently used commands and instruct ions for LCD

    * DDRAM address given in LCD basics section see Figure 2,3,4

    ** CGRAM address from 0x00 to 0x3F, 0x00 to 0x07 for char1 and so on..

    The table above will help you while writing programs for LCD. But after you are donetesting with the table 4, i recommend you to use table 3 to get more grip on working with

    LCD and trying your own commands. In the next section of the tutorial we will see theinitialization with some of the coding examples in C as well as assembly.

    LCD InitializationBefore using the LCD for display purpose, LCD has to be initialized either by the internalreset circuit or sending set of commands to initialize the LCD. It is the user who has to

    decide whether an LCD has to be initialized by instructions or by internal reset circuit. wewill dicuss both ways of initialization one by one.

    Initialization by internal Reset Circuit

    An internal reset circuit automatically initializes the HD44780U when the power isturned on. The following instructions are executed during the initialization. The busy flag(BF) is kept in the busy state until the initialization ends (BF = 1). The busy state lasts for

    10 ms after VCC rises to 4.5 V.

    Display clear

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    9/31

    Function set:DL = 1; 8-bit interface data

    N = 0; 1-line displayF = 0; 5 x 8 dot character font

    Display on/off control:

    D = 0; Display offC = 0; Cursor offB = 0; Blinking off

    Entry mode set:I/D = 1; Increment by 1

    S = 0; No shift

    Note: If the electrical characteristics conditions listed under the table Power Supply

    Conditions Using Internal Reset Circuit are not met, the internal reset circuit will notoperate normally and will fail to initialize the HD44780U. For such a case, initial-ization

    must be performed by the MCU as explained in the section, Initializing by Instruction.

    As mentioned in the Note, there are certain condtions that has to be met, if user want touse initialization by internal reset circuit. These conditions are shown in the Table 5

    below.

    Table 5: Power Supply condition for Internal Reset circuit

    Figure 7 shows the test condition which are to be met for internal reset circuit to beactive.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    10/31

    Figure 7: Internal Power Supply reset

    Now the problem with the internal reset circuit is, it is highly dependent on power supply,

    to meet this critical power supply conditions is not hard but are difficult to achive whenyou are making a simple application. So usually the second menthod i.e. Initialization by

    instruction is used and is recommended most of the time.

    Initialization by instructions

    Initializing LCD with instructions is really simple. Given below is a flowchart thatdescribles the step to follow, to initialize the LCD.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    11/31

    Figure 8: Flow chart for LCD initialization

    As you can see from the flow chart, the LCD is initialized in the following sequence...1) Send command 0x30 - Using 8-bit interface

    2) Delay 20ms3) Send command 0x30 - 8-bit interface

    4) Delay 20ms5) Send command 0x30 - 8-bit interface

    6) Delay 20ms7) Send Function set - see Table 4 for more information

    8) Display Clear command9) Set entry mode command - explained below

    The first 3 commands are usually not required but are recomended when you are using 4-

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    12/31

    bit interface. So you can program the LCD starting from step 7 when working with 8-bitinterface. Function set command depends on what kind of LCD you are using and what

    kind of interface you are using (see Table 4 in LCD Command section).

    LCD Entry mode

    From Table 3 in command section, you can see that the two bits decide the entry modefor LCD, these bits are:a) I/D - Increment/Decrement bit

    b) S - Display shift.With these two bits we get four combinations of entry mode which are

    0x04,0x05,0x06,0x07 (see table 3 in LCD Command section). So we get different resultswith these different entry modes. Normally entry mode 0x06 is used which is No shift

    and auto incremement. I recommend you to try all the possible entry modes and see theresults, I am sure you will be surprised.

    Programming example for LCD Initialization

    CODE:LCD_data equP2 ;LCD Data port

    LCD_D7 equP2.7 ;LCD D7/Busy Flag

    LCD_rs equP1.0 ;LCD Register Select

    LCD_rw equP1.1 ;LCD Read/Write

    LCD_en equP1.2 ;LCD Enable

    LCD_init:

    mov LCD_data,#38H ;Function set: 2 Line, 8-bit,

    5x7 dots

    clr LCD_rs ;Selected command registerclr LCD_rw ;We are writing in

    instruction register

    setb LCD_en ;Enable H->L

    clr LCD_en

    acall LCD_busy ;Wait for LCD to process the

    command

    mov LCD_data,#0FH ;Display on, Curson blinking

    command

    clr LCD_rs ;Selected instruction

    register

    clr LCD_rw ;We are writing ininstruction register

    setb LCD_en ;Enable H->L

    clr LCD_en

    acall LCD_busy ;Wait for LCD to process the

    command

    mov LCD_data,#01H ;Clear LCD

    clr LCD_rs ;Selected command register

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    13/31

    clr LCD_rw ;We are writing in

    instruction register

    setb LCD_en ;Enable H->L

    clr LCD_en

    acall LCD_busy ;Wait for LCD to process the

    command

    mov LCD_data,#06H ;Entry mode, auto increment

    with no shift

    clr LCD_rs ;Selected command register

    clr LCD_rw ;We are writing in

    instruction register

    setb LCD_en ;Enable H->L

    clr LCD_en

    acall LCD_busy ;Wait for LCD to process the

    command

    ret ;Return from routine

    Now we can do the same thing in C, I am giving example using Keil C. Similar code can

    be written for SDCC.

    CODE:#include .

    #define LCD_data P2

    #define LCD_D7 P2_7

    #define LCD_rs P1_0

    #define LCD_rw P1_1

    #define LCD_en P1_2

    void LCD_init()

    {

    LCD_data =0x38; //Function set: 2 Line, 8-

    bit, 5x7 dots

    LCD_rs =0; //Selected command register

    LCD_rw =0; //We are writing in data

    register

    LCD_en =1; //Enable H->L

    LCD_en =0;

    LCD_busy(); //Wait for LCD to processthe command

    LCD_data =0x0F; //Display on, Curson

    blinking command

    LCD_rs =0; //Selected command register

    LCD_rw =0; //We are writing in data

    register

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    14/31

    LCD_en =1; //Enable H->L

    LCD_en =0;

    LCD_busy(); //Wait for LCD to process

    the command

    LCD_data =0x01; //Clear LCD

    LCD_rs =0; //Selected command registerLCD_rw =0; //We are writing in data

    register

    LCD_en =1; //Enable H->L

    LCD_en =0;

    LCD_busy(); //Wait for LCD to process

    the command

    LCD_data =0x06; //Entry mode, auto

    increment with no shift

    LCD_rs =0; //Selected command register

    LCD_rw =0; //We are writing in dataregister

    LCD_en =1; //Enable H->L

    LCD_busy();

    }

    With the help of the above code, you are able to initialize the LCD. Now there

    is a function/subroutine coming in the code i.e. LCD_busy, which is used to put

    delay for LCD so that there should not be any command or data sent to the

    LCD untill it finish executing the command. More on this delay routine is

    explained in the next section.

    Reading the busy FlagAs discussed in the previous section, there must be some delay which is needed to be

    there for LCD to successfully process the command or data. So this delay can be madeeither with a delay loop of specified time more than that of LCD process time or we can

    read the busy flag, which is recomended. The reason to use busy flag is that delayproduced is almost for the exact amount of time for which LCD need to process the time.

    So is best suited for every application.

    Steps to read busy flag

    when we send the command, the BF or D7th bit of the LCD becomes 1 and as soon as the

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    15/31

    command is processed the BF = 0. Following are the steps to be kept in mind whilereading the Busy flag.

    Select command register

    Select read operation

    Send enable signal Read the flag

    So following the above steps we can write the code in assembly as below...

    CODE:;Ports used are same as the previous example

    LCD_busy:

    setb LCD_D7 ;Make D7th bit of LCD data

    port as i/p

    setb LCD_en ;Make port pin as o/p

    clr LCD_rs ;Select command register

    setb LCD_rw ;we are reading

    check:

    clr LCD_en ;Enable H->L

    setb LCD_en

    jb LCD_D7,check ;read busy flag again and

    again till it becomes 0

    ret ;Return from busy routine

    The equivalent C code Keil C compiler. Similar code can be written for SDCC.

    CODE:void LCD_busy()

    {

    LCD_D7 =1; //Make D7th bit of LCD as i/p

    LCD_en =1; //Make port pin as o/p

    LCD_rs =0; //Selected command register

    LCD_rw =1; //We are reading

    while(LCD_D7){ //read busy flag again and

    again till it becomes 0LCD_en =0; //Enable H->L

    LCD_en =1;

    }

    }

    The above routine will provide the necessary delay for the instructions to complete. If

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    16/31

    you dont want to read the busy flag you can simply use a delay routine to provide the aspecific ammount of delay. A simple delay routine for the LCD is given below.

    CODE:LCD_busy:

    mov r7,#50Hback:

    mov r6,#FFH

    djnzr6,$

    djnzr7,back

    ret ;Return from busy

    routine

    CODE:void LCD_busy()

    {

    unsignedchar i,j;

    for(i=0;i

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    17/31

    CODE:;Ports used are same as the previous example

    ;Routine to send command to LCD

    LCD_command:

    mov LCD_data,A ;Move the command to LCD port

    clr LCD_rs ;Selected command register

    clr LCD_rw ;We are writing in

    instruction register

    setb LCD_en ;Enable H->L

    clr LCD_en

    acall LCD_busy ;Wait for LCD to process the

    command

    ret ;Return from busy routine

    ; Usage of the above routine

    ; A will carry the command for LCD

    ; e.g. we want to send clear LCD command

    ;

    ; mov a,#01H ;01H is command for clearing LCD

    ; acall LCD_command ;Send the command

    The equivalent C code Keil C compiler. Similar code can be written for SDCC.

    CODE:void LCD_command(unsignedchar var)

    {

    LCD_data = var; //Function set: 2 Line, 8-

    bit, 5x7 dots

    LCD_rs =0; //Selected command register

    LCD_rw =0; //We are writing in

    instruction register

    LCD_en =1; //Enable H->L

    LCD_en =0;

    LCD_busy(); //Wait for LCD to process

    the command

    }

    // Using the above function is really simple

    // var will carry the command for LCD

    // e.g.

    //

    // LCD_command(0x01);

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    18/31

    Setting cursor position on LCDTo set the cursor position on LCD, we need to send the DDRAM address...

    CODE:Bit7 6 5 4 3 2 1 0

    1 AD6 AD5 AD4 AD3 AD2 AD1 AD0

    The seventh bit is always 1, and bit 0 to 7 are DDRAM address (See the

    introduction section of LCD). so if you want to put the cursor on first position

    the address will be '0000000B' in binary and 7th bit is 1. so address will be

    0x80, so for DDRAM all address starts from 0x80.

    For 2 line and 16 character LCD. The adress from 0x80 to 0x8F are visible on

    first line and 0xC0 to 0xCF is visible on second line, rest of the DDRAM area

    is still available but is not visible on the LCD, if you want to check this thing,

    then simply put a long sting greater than 16 character and shift the entire

    display, you will see all the missing character coming from the back.. this way

    you can make scrolling line on LCD (see more on shifting display in

    commands section).

    Below is an example for setting cursor position on LCD.

    CODE:;We are placing the cursor on the 4th position

    ;so the DDRAM address will be 0x03

    ;and the command will be 0x80+0x03 = 0x83

    mova,#83H ;load the command

    acall LCD_command ;send command to LCD

    CODE:// to do the same thing is C

    // as we done before

    LCD_command(0x83);

    Sending Data to LCDTo send data we simply need to select the data register. Everything is same as

    the command routine. Following are the steps:

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    19/31

    Move data to LCD port

    select data register

    select write operation

    send enable signal

    wait for LCD to process the data

    Keeping these steps in mind we can write LCD command routine as.

    CODE:;Ports used are same as the previous example

    ;Routine to send data (single character) to LCD

    LCD_senddata:

    mov LCD_data,A ;Move the command toLCD port

    setb LCD_rs ;Selected data register

    clr LCD_rw ;We are writing

    setb LCD_en ;Enable H->L

    clr LCD_en

    acall LCD_busy ;Wait for LCD to

    process the data

    ret ;Return from busy

    routine

    ; Usage of the above routine

    ; A will carry the character to display on LCD

    ; e.g. we want to print A on LCD

    ;

    ; mov a,#'A' ;Ascii value of 'A' will be

    loaded in accumulator

    ; acall LCD_senddata ;Send data

    The equivalent C code Keil C compiler. Similar code can be written for SDCC.

    CODE:void LCD_senddata(unsignedchar var)

    {

    LCD_data = var; //Function set: 2 Line, 8-

    bit, 5x7 dots

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    20/31

    LCD_rs =1; //Selected data register

    LCD_rw =0; //We are writing

    LCD_en =1; //Enable H->L

    LCD_en =0;

    LCD_busy(); //Wait for LCD to process

    the command}

    // Using the above function is really simple

    // we will pass the character to display as argument

    to function

    // e.g.

    //

    // LCD_senddata('A');

    Now you have seen that its really easy to send command and data to LCD. Nowwhat if we have a string to send to LCD? how we are going to do that?

    Is simple, we will store the LCD string in the ROM of controller and call the

    string character by character. A simple exmple is shown below.

    CODE:;Sending string to LCD Example

    LCD_sendstring:clr a ;clear Accumulator

    for any previous data

    movc a,@a+dptr ;load the first

    character in accumulator

    jz exit ;go to exit if zero

    acall lcd_senddata ;send first char

    inc dptr ;increment data

    pointer

    sjmp LCD_sendstring ;jump back to send

    the next characterexit:

    ret ;End of routine

    ; Usage of the above routine

    ; DPTR(data pointer) will carry the address

    ; of string to send to LCD.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    21/31

    ; e.g. we want to print "LCD Tutorial" on LCD then

    ;

    ; mov dptr,#my_string ;my_string is the label

    where the string is stored

    ; acall LCD_sendstring ;Send string

    ;; To store a string..

    ; my_string:

    ; DB "LCD Tutorial", 00H

    ; 00H indicate that string is finished.

    The equivalent C code Keil C compiler. Similar code can be written for SDCC.

    CODE:

    void LCD_sendstring(unsignedchar*var){

    while(*var) //till string ends

    LCD_senddata(*var++); //send characters one

    by one

    }

    // Using the above function is really simple

    // we will pass the string directly to the function

    // e.g.

    //

    // LCD_sendstring("LCD Tutorial");

    Now we are ready with sending data and sending command to LCD. Now the

    last and final section which is creating custom characters or patterns to display

    on LCD. Please proceed to the next section to read more.

    CGRAM and Character BuildingAs already explained, all character based LCD of type HD44780 has CGRAM area to

    create user defined patterns. For making custom patterns we need to write values to theCGRAM area defining which pixel to glow. These values are to be written in the

    CGRAM adress starting from 0x40. If you are wondering why it starts from 0x40? Thenthe answer is given below.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    22/31

    Bit 7 is 0 and Bit 6 is 1, due to which the CGRAM adress command starts from 0x40,where the address of CGRAM (Acg) starts from 0x00. CGRAM has a total of 64 Bytes.When you are using LCD as 5x8 dots in function set then you can define a total of 8 user

    defined patterns (1 Byte for each row and 8 rows for each pattern), where as when LCDis working in 5x10 dots, you can define 4 user defined patterns.

    Lets take an of bulding a custom pattern. All we have to do is make a pixel-map of 7x5

    and get the hex or decimal value or hex value for each row, bit value is 1 if pixel isglowing and bit value is 0 if pixel is off. The final 7 values are loaded to the CGRAM one

    by one. As i said there are 8 rows for each pattern, so last row is usually left blank (0x00)for the cursor. If you are not using cursor then you can make use of that 8th row also. so

    you get a bigger pattern.

    To explain the above explaination in a better way. I am going to take an example. Lets

    make a "Bell" pattern as shown below.

    Now we get the values for each row as shown.

    Bit: 4 3 2 1 0 - Hex

    Row1: 0 0 1 0 0 - 0x04Row2: 0 1 1 1 0 - 0x0E

    Row3: 0 1 1 1 0 - 0x0ERow4: 0 1 1 1 0 - 0x0E

    Row5: 1 1 1 1 1 - 0x1FRow6: 0 0 0 0 0 - 0x00

    Row7: 0 0 1 0 0 - 0x04Row8: 0 0 0 0 0 - 0x00

    We are not using row 8 as in our pattern it is not required. if you are using cursor then it

    is recommended not to use the 8th row. Now as we have got the values. We just need to

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    23/31

    put these values in the CGRAM. You can decided which place you want to store in.Following is the memory map for custom patterns in CGRAM.

    Memory Map

    Pattern No. CGRAM Address (Acg)

    1 0x00 - 0x072 0x08 - 0x0F

    3 0x10 - 0x17

    4 0x18 - 0x1F

    5 0x20 - 0x27

    6 0x28 - 0x2F

    7 0x30 - 0x37

    8 0x38 - 0x3F

    We can point the cursor to CGRAM address by sending command, which is 0x40 +

    CGRAM address (For more information please see Table 4 in commands section). Letssay we want to write the Bell pattern at second pattern location. So we send the command

    as 0x48 (0x40 + 0x08), and then we send the pattern data. Below is a small programmingexample to do this.

    CODE:;LCD Ports are same as discussed in previous sections

    LCD_build:

    mov A,#48H ;Load the location

    where we want to storeacall LCD_command ;Send the command

    mov A,#04H ;Load row 1 data

    acall LCD_senddata ;Send the data

    mov A,#0EH ;Load row 2 data

    acall LCD_senddata ;Send the data

    mov A,#0EH ;Load row 3 data

    acall LCD_senddata ;Send the data

    mov A,#0EH ;Load row 4 data

    acall LCD_senddata ;Send the data

    mov A,#1FH ;Load row 5 data

    acall LCD_senddata ;Send the data

    mov A,#00H ;Load row 6 data

    acall LCD_senddata ;Send the data

    mov A,#04H ;Load row 7 data

    acall LCD_senddata ;Send the data

    mov A,#00H ;Load row 8 data

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    24/31

    acall LCD_senddata ;Send the data

    ret ;Return from routine

    The above routine will create bell character at pattern location 2. To display the above

    generated pattern on LCD, simply load the pattern location (0,1,2,...7) and call theLCD_senddata subroutine. Now we can also write the above routine in C as...

    CODE://LCD Ports are same as discussed in previous

    sections

    void LCD_build(){

    LCD_command(0x48); //Load the location

    where we want to store

    LCD_senddata(0x04); //Load row 1 data

    LCD_senddata(0x0E); //Load row 2 dataLCD_senddata(0x0E); //Load row 3 data

    LCD_senddata(0x0E); //Load row 4 data

    LCD_senddata(0x1F); //Load row 5 data

    LCD_senddata(0x00); //Load row 6 data

    LCD_senddata(0x04); //Load row 7 data

    LCD_senddata(0x00); //Load row 8 data

    }

    I think now most of you find programing in C more simple than assembly. We can also

    summarize the above in a simple small routine so that you can simply call the buildroutine providing a pointer to array containing the build data. Below example shows how

    to do it.

    CODE://Input:

    // location: location where you want to store

    // 0,1,2,....7

    // ptr: Pointer to pattern data

    //

    //Usage:

    //pattern[8]={0x04,0x0E,0x0E,0x0E,0x1F,0x00,0x04,0x00};

    // LCD_build(1,pattern);

    //

    //LCD Ports are same as discussed in previous

    sections

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    25/31

    void LCD_build(unsigned char location, unsigned char

    *ptr){

    unsigned char i;

    if(location

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    26/31

    IntroductionTill now whatever we discussed in the previous part of ths LCD tutorial, we were dealingwith 8-bit mode. Now we are going to learn how to use LCD in 4-bit mode. There are

    many reasons why sometime we prefer to use LCD in 4-bit mode instead of 8-bit. Onebasic reason is lesser number of pins are needed to interface LCD.

    In 4-bit mode the data is sent in nibbles, first we send the higher nibble and then the

    lower nibble. To enable the 4-bit mode of LCD, we need to follow special sequence ofinitialization that tells the LCD controller that user has selected 4-bit mode of operation.

    We call this special sequence as resetting the LCD. Following is the reset sequence ofLCD.

    Wait for abour 20mS Send the first init value (0x30)

    Wait for about 10mS Send second init value (0x30)

    Wait for about 1mS

    Send third init value (0x30)

    Wait for 1mS Select bus width (0x30 - for 8-bit and 0x20 for 4-bit)

    Wait for 1mS

    The busy flag will only be valid after the above reset sequence. Usually we do not use

    busy flag in 4-bit mode as we have to write code for reading two nibbles from the LCD.

    Instead we simply put a certain ammount of delay usually 300 to 600uS. This delay mightvary depending on the LCD you are using, as you might have a different crystalfrequency on which LCD controller is running. So it actually depends on the LCD

    module you are using. So if you feel any problem running the LCD, simply try toincrease the delay. This usually works. For me about 400uS works perfect.

    LCD connections in 4-bit Mode

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    27/31

    Above is the connection diagram of LCD in 4-bit mode, where we only need 6 pins to

    interface an LCD. D4-D7 are the data pins connection and Enable and Register select arefor LCD control pins. We are not using Read/Write (RW) Pin of the LCD, as we are only

    writing on the LCD so we have made it grounded permanently. If you want to use it..then you may connect it on your controller but that will only increase another pin and does

    not make any big difference. Potentiometer RV1 is used to control the LCD contrast. Theunwanted data pins of LCD i.e. D0-D3 are connected to ground.

    Sending data/command in 4-bit ModeWe will now look into the common steps to send data/command to LCD when working

    in 4-bit mode. As i already explained in 4-bit mode data is sent nibble by nibble, first wesend higher nibble and then lower nibble. This means in both command and data sending

    function we need to saperate the higher 4-bits and lower 4-bits.

    The common steps are:

    Mask lower 4-bits

    Send to the LCD port

    Send enable signal Mask higher 4-bits

    Send to LCD port

    Send enable signal

    We are done with the theory part now, In the next section we will take a look at theprogramming microcontroller to control LCD in 4-bit mode.

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    28/31

    LCD interfacing with Microcontrollers tutorial - 4-bit Mode

    4-bit InitializationInitialization of LCD is completed only after the reset sequence and basic initializationcommands. We have already discussed about the reset sequence of the lcd in the previous

    section. So lets look at the programming now...

    Assembly ProgramCODE:;In this whole 4-bit tutorial LCD is connected to

    ;my controller in following way...

    ;D4 - P3.0

    ;D5 - P3.1

    ;D6 - P3.2

    ;D7 - P3.3

    ;EN - P3.7

    ;RS - P3.5

    lcd_port equP3 ;LCD connected to Port3

    en equP3.7 ;Enable connected to P3.7

    rs equP3.5 ;Register select to P3.5

    lcd_reset: ;LCD reset sequence

    mov lcd_port,#0FFHmov delay,#20 ;20mS delay

    acall delayms

    mov lcd_port,#83H ;Data = 30H, EN = 1, First

    Init

    mov lcd_port,#03H ;Data = 30H, EN = 0

    mov delay,#15 ;Delay 15mS

    acall delayms

    mov lcd_port,#83H ;Second Init, Data = 30H,

    EN = 1

    mov lcd_port,#03H ;Data = 30H, EN = 0

    mov delay,#5 ;Delay 5mSacall delayms

    mov lcd_port,#83H ;Third Init

    mov lcd_port,#03H

    mov delay,#5 ;Delay 5mS

    acall delayms

    mov lcd_port,#82H ;Select Data width (20H for

    4bit)

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    29/31

    mov lcd_port,#02H ;Data = 20H, EN = 0

    mov delay,#5 ;Delay 5mS

    acall delayms

    ret

    lcd_init:

    acall lcd_reset ;Call LCD Reset sequence

    mova,#28H ;4-bit, 2 line, 5x7 dots

    acall lcd_cmd ;Call LCD command

    mova,#0CH ;Display ON cursor OFF

    acall lcd_cmd ;Call LCD command

    mova,#06H ;Set entry mode (Auto

    increment)

    acall lcd_cmd ;Call LCD command

    mova,#80H ;Bring cursor to line 1

    acall lcd_cmd ;Call LCD command

    ret

    C ProgramCODE://The pins used are same as explained earlier

    #define lcd_port P3

    //LCD Registers addresses

    #define LCD_EN 0x80#define LCD_RS 0x20

    void lcd_reset()

    {

    lcd_port =0xFF;

    delayms(20);

    lcd_port =0x03+LCD_EN;

    lcd_port =0x03;

    delayms(10);

    lcd_port =0x03+LCD_EN;

    lcd_port =0x03;delayms(1);

    lcd_port =0x03+LCD_EN;

    lcd_port =0x03;

    delayms(1);

    lcd_port =0x02+LCD_EN;

    lcd_port =0x02;

    delayms(1);

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    30/31

    }

    void lcd_init ()

    {

    lcd_reset(); // Call LCD reset

    lcd_cmd(0x28); // 4-bit mode - 2 line - 5x7

    font.

    lcd_cmd(0x0C); // Display no cursor - no

    blink.

    lcd_cmd(0x06); // Automatic Increment - No

    Display shift.

    lcd_cmd(0x80); // Address DDRAM with 0 offset

    80h.

    }

    Sending Dommand/Data to LCD in 4-bit mode Assembly ProgramCODE:lcd_cmd: ;LCD command Routine

    mov temp,a ;Save a copy of command to

    temp

    swapa ;Swap to use higher nibble

    anla,#0FH ;Mask the first four bits

    adda,#80H ;Enable = 1, RS = 0mov lcd_port,a ;Move it to lcd port

    anla,#0FH ;Enable = 0, RS = 0

    mov lcd_port,a ;Move to lcd port

    mova,temp ;Reload the command from temp

    anla,#0FH ;Mask first four bits

    adda,#80H ;Enable = 1

    mov lcd_port,a ;Move to port

    anla,#0FH ;Enable = 0

    mov lcd_port,a ;Move to lcd port

    mov delay,#1 ;delay 1 ms

    acall delayms

    ret

    lcd_dat: ;LCD data Routine

    mov temp,a ;Keep copy of data in temp

    swapa ;We need higher nibble

  • 8/2/2019 LCD Interfacing With Microcontrollers Tutorial

    31/31

    anla,#0FH ;Mask first four bits

    adda,#0A0H ;Enable = 1, RS = 1

    mov lcd_port,a ;Move to lcd port

    nop

    clr en ;Enable = 0

    mova,temp ;Reload the data from temp

    anla,#0FH ;we need lower nibble now

    adda,#0A0H ;Enable = 1, RS = 1

    mov lcd_port,a ;Move to lcd port

    nop

    clr en ;Enable = 0

    mov delay,#1 ;Delay 1mS

    acall delayms

    ret

    C ProgramCODE:void lcd_cmd (char cmd)

    {

    lcd_port =((cmd >>4)&0x0F)|LCD_EN;

    lcd_port =((cmd >>4)&0x0F);

    lcd_port =(cmd &0x0F)|LCD_EN;lcd_port =(cmd &0x0F);

    delayus(200);

    delayus(200);

    }

    void lcd_data (unsignedchar dat)

    {

    lcd_port =(((dat >>4)&0x0F)|LCD_EN|LCD_RS);

    lcd_port =(((dat >>4)&0x0F)|LCD_RS);

    lcd_port =((dat &0x0F)|LCD_EN|LCD_RS);

    lcd_port =((dat &0x0F)|LCD_RS);

    delayus(200);

    delayus(200);

    }