Sunday, December 4, 2011

§ Interfacing HD44780 LCD – Part3

Hello Friends,

                  In this post I am going to share my 16x2 LCD library Functions with you. This library will help you to easily interface 16x2 LCD with AVR. In my previous two posts I explain the internal operation of LCD and the concept to print characters on LCD. In the last post I also explain three main functions-

1.      Send_LCD_Char(uint8_t data);
2.      Send_LCD_Cmd(uint8_t data);
3.      LCD_init();

Using first two functions I write some other functions which will help you to pickup more command on  this LCD. Here I am going to explain these functions one by one –


§ Move the cursor at specified location on the screen:

 

DDRAM area Highlighted in green is responsible to show characters on LCD. We have to move cursor in this area means to print any character on LCD we have to first set the DDRAM address or location where our character will be print. To access DDRAM there is some commands –

 
For LCD 1st Line at (0, 0) -> 0x80
For LCD 2nd Line at (0, 1) -> 0xC0

If we want to move cursor at (1,1) then we have to send command: (0xC0+1)
Or in practical way we have to write:  Send_LCD_Cmd(0xC0 + 1 );

To move cursor at any location on the screen I write a function:
LCD_gotoxy(uint8_t  x, uint8_t  y);

#define LCD_1ST_LINE     0x80
#define LCD_2ND_LINE     0xC0

void LCD_gotoxy(uint8_t x, uint8_t y)
{
  if(!y)Send_LCD_Cmd(LCD_1ST_LINE  + x);
  else Send_LCD_Cmd(LCD_2ND_LINE  + x);
 }

Example : LCD_gotoxy(4,0);

 
§ Print a Character on LCD:  I already discuss this topic and it’s Function in my previous post. 

      Send_LCD_Char(uint8_t  data);

Ex. Send_LCD_Char(‘P’);

 
 If you want to print this character at (4,0) then :

  LCD_gotoxy(4,0);
  Send_LCD_Char(‘P’);

 

§ Print a String on the screen at specified location:  Now you can easily make a function for print a string using previous two functions.

     void LCD_printStr(uint8_t x,uint8_t y,char *s);
   
     Ex. LCD_printStr(0,0,”PRATYUSH”);

 
void LCD_printStr(uint8_t x,uint8_t y,char *s)
{
   LCD_gotoxy(x,y);
     while(*s)
      Send_LCD_Char(*s++);
 }


§ Print Numbers on LCD: This LCD is a character LCD we have to send ascii value of a character. If we want to print ‘0’ then we have to write :

                                    Send_LCD_Char(48);  or  Send_LCD_Char(‘0’);

But if we want to print 123 then?? Using a small trick in ‘C’ we can do this. We have to first break our number in digits then on by one send the ascii values of these digits on the screen. I write a function for displaying a number on the screen at specified location of specified length:

void LCD_printInt(uint8_t x,uint8_t y,uint8_t len,uint16_t n);

len - length (should be <=5)
n   - Integer number

Ex.  void LCD_printInt(4,0,3,123);
 


void LCD_printInt(uint8_t x,uint8_t y,uint8_t len,uint16_t n)
{
char num_arr[5]={0,0,0,0,0};
int i=len-1;

 while(n)
 {
   num_arr[i--]=n%10;
   n=n/10;
  }
 LCD_gotoxy(x,y);
 for(i=0;i<len;i++)
  {
   Send_LCD_Char('0' + num_arr[i]);
   }
}


Note : If you write: LCD_printInt(4,0,2,1234); then it will display ‘34’ on the screen. So remember to set correct length in the function.


§ Clear the screen: 

LCD_clr();

void LCD_clr()
 {
   Send_LCD_Cmd(0x01);
  }


§ Print Custom Characters: (user define characters)
In my previous post I explain that CGRAM is used to store user define characters. We have to store the bitmap images of these characters in CGRAM area starts from 0x40. In DDRAM location 0 to 7 is reserved as address of custom characters.

** If you write: Send_LCD_Char(0);  then it will print custom character from location 0 of DDRAM.We have 7 locations in DDRAM so we can store maximum of 7 custom characters at a time.

 
To load custom character use the function below :

Load_CustomChar(const uint8_t *cc,uint8_t loc);

Ex: Load_CustomChar(cc0,0);



const uint8_t cc0[8]={21,10,21,10,21,10,21,0};

void Load_CustomChar(const uint8_t *cc,uint8_t loc)
{
 uint8_t i;
 Send_LCD_Cmd(0x40+(loc*8));//Address where custom character is stored

    for (i=0;i<8;i++)
    {
      Send_LCD_Char(cc[i]);
     }
     _delay_ms(10);
}
cc0 is a array which contain bitmap image of custom character.


§ Scroll LCD Screen:You can scroll LCD display in left or right using two commands:

 SHIFT_DISP_RIGHT  -  0x1C
   SHIFT_DISP_LEFT   -  0x18

void Scroll_LCD()
 {
  uint8_t s;
  for(s=0;s<8;s++)
  {
  Send_LCD_Cmd(SHIFT_DISP_RIGHT);
  Delayms(300);
  }
 for(s=0;s<8;s++)
  {
  Send_LCD_Cmd(SHIFT_DISP_LEFT);
   Delayms(300);
  }
 }
Ex.Scroll_LCD();

 
§ Animation on LCD: Using custom characters you can design interactive animation. Here I am going to share a Function in which you can display a bar and fill its pixels.

 Draw_Bar( uint8_t  x, uint8_t  y, uint8_t  len, uint8_t  pxl );

x,y- is the location where you want to show bar
len – is the length of bar
pxl – how many pixel you want to fill


void Draw_Bar(uint8_t x,uint8_t y,uint8_t len,uint8_t pxl)
{
 Load_custom_bars();
 int i,cc;
 LCD_gotoxy(x,y);
 for(i=0;i<len;i++)
  {
   if(((i*5)+5)>pxl)
    {
     if((i*5)>pxl){cc=0;}
     else{cc=pxl%5;}
     }
   else {cc=5;}
   Send_LCD_Char(cc);
   _delay_ms(2);
  }
}

Ex. Draw_Bar(0,0,12,26);
 Output:


§Using LCD library:
//---------------------------------------------------------------------------
//***************16x2 HD44780 LCD DRIVER ************************************
// File Name  :  ew_lcd.c
//Target MCU  :  ATtiny2313,ATmega8,ATmega16/32 @ 16MHz
//  Compiler  :  WinAVR
//    Auther  :  Pratyush Gehlot, Rajasthan, India
//      Blog  :  www.electronicswork.blogspot.com
//***************************************************************************
//---------------------------------------------------------------------------

Step1. Copy LCD Library file ‘ew_lcd.c’ in your project folder.
Step2. Include this file in main code file Ex. #include “ew_lcd.c”
Step3. Initialize lcd in main program. Ex. LCD_init();

Circuit Diagram:
 
Tutorial 1:  Program to display some text on screen – 

Code:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "ew_lcd.c"

int main(void)
{
 LCD_init();
  LCD_printStr(0,0"HELLO!");
    LCD_printStr(2,1,"I AM HD44780");
   }
 return 0;                         
}
Output:


Tutorial 2: Display Custom characters

Code:

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "ew_lcd.c"

const uint8_t cc0[8]={21,10,21,10,21,10,21,0};//chess
const uint8_t cc1[8]={0,27,27,0,4,17,14,0};//smily
const uint8_t cc2[8]={16,24,28,30,28,24,16,0};//arrow
const uint8_t cc3[8]={31,31,31,31,31,31,31,0};//block
const uint8_t cc4[8]={0,31,28,28,28,28,31,0};//bar
const uint8_t cc5[8]={31,17,17,17,17,17,31,0};//rectangle
const uint8_t cc6[8]={31,31,31,27,31,31,31,0};//hole
const uint8_t cc7[8]={0,10,10,0,17,14,6,0};//happy

void Load_CustumChars()
{
 Load_CustomChar(cc0,0);
 Load_CustomChar(cc1,1);
 Load_CustomChar(cc2,2);
 Load_CustomChar(cc3,3);
 Load_CustomChar(cc4,4);
 Load_CustomChar(cc5,5);
 Load_CustomChar(cc6,6);
 Load_CustomChar(cc7,7);
 }

int main(void)
{
 LCD_init();
 Load_CustumChars();
 LCD_printStr(0,0,"Custom Character");
 int i;

 while(1){
  for(i=0;i<8;i++)
  {
   LCD_gotoxy(i*2,1);
    Send_LCD_Char(i);
   }
  }     
      
Output:


Tutorial 3: Bar Animation

Code:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "ew_lcd.c"

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

 while(1){
  LCD_printStr(0,0,"Loading...  %");
   for(i=0;i<80;i++)
    {
      Draw_Bar(0,1,16,i);
       LCD_printInt(10,0,2,i);
    }
   }
 return 0;                         
}
                   

Output :(screenshot)
 
Downloads: 
LCD Driver : ew_lcd.c
Tutorial 1 Files
Tutorial 2 Files
Tutorial 3 Files

Video:

                                                                                                                           
                                                                                                                ~Pratyush Gehlot

5 comments:

  1. Hi,

    I used your blog to get my routines right, it helped me a lot! However, I think there is a better way to write the printInt function. Mine is as following:

    LCD_entryMode(0,0); //From right to left
    //for(j=i-1;j>=0;j--) //The old code
    for(j=0;j<i;j++) //The new code
    {
    LCD_sendChar('0' + num_arr[j]);
    }
    for(j=i;j<len;j++)
    {
    LCD_sendChar(' ');
    }
    LCD_entryMode(1,0); //From left to right

    LCD_entryMode is my function to set the cursor shift, set in bytes DB1 and DB0. So I print the integer from right-to-left instead of left-to-right. This way the decimal seperator is allways in the same place.

    ReplyDelete
  2. @Nick thanks for pointing me about this, now I update this function in the post and now this function does not require LCD_entryMode function.

    ReplyDelete
  3. hey
    the files are not available anymore, can please upload them again?

    ReplyDelete
  4. can you please enable links for downloading the header and example files

    ReplyDelete

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