Get Adobe Flash player
FacebookTwitterGoogle+
English Arabic French German Italian Portuguese Russian Spanish

Did you know?

An electric oven uses one kilowatt-hour of electricity in about 20 minutes, but one kilowatt-hour will power a TV for 3 hours, run a 100-watt bulb for 12 hours, and keep an electric clock ticking for 3 months.
 

Help us stay online:

small donate

lcd exampleIn this example we will make small project that uses 2x16 character LCD display to write some text and variables to it. You can read more about how these displays work in LCD character Display article. This is very good library that can be very easily adjusted to other microcontroller families (8051,  Pic, dsPic, ARM..) just by changing low level (pin change) functions while everything else remains the same. Another advantage of this is that every pin is set independently, so you do not need to have whole 8 pin port to send data. You only need to define any pin on any port that is available to you. Original library that I used had some flaws and no support for two line display, so I modified and improved it.


Below you can find source code with key lines highlighted:

#include <mega8.h>
#include <delay.h>
#include <stdlib.h>
#define LCD_RS    PORTD.2    // Register select
#define LCD_EN    PORTD.3    // Enable
#define LCD_D4 PORTD.4    // Data bits
#define LCD_D5 PORTD.5    // Data bits
#define LCD_D6 PORTD.6    // Data bits
#define LCD_D7 PORTD.7    // Data bits
#define    LCD_STROBE    ((LCD_EN = 1),(LCD_EN=0))
char buf[4];
char b1,b2,b3;
/*
 *    LCD interface example
 *    Uses routines from delay.c
 *    This code will interface to a standard LCD controller
 *    like the Hitachi HD44780. It uses LCD display in 4 bit mode, with
 *    the hardware connected as follows (the standard 14 pin 
 *    LCD connector is used):
 *    
 *    PORTB bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
 *    PORTA bit 2 is connected to the LCD RS input (register select)
 *    PORTA bit 3 is connected to the LCD EN bit (enable)
 *    
 *    To use these routines, set up the port I/O (TRISA, TRISB) then
 *    call lcd_init(), then other routines as required.
 *
 * Copywrite Craig Lee 1998
 *    
 */
/* write a byte to the LCD in 4 bit mode */
void
lcd_write(unsigned char c)
{
    if(c & 0x80) LCD_D7=1; else LCD_D7=0;
    if(c & 0x40) LCD_D6=1; else LCD_D6=0;
    if(c & 0x20) LCD_D5=1; else LCD_D5=0;
    if(c & 0x10) LCD_D4=1; else LCD_D4=0;
    LCD_STROBE;
    if(c & 0x08) LCD_D7=1; else LCD_D7=0;
    if(c & 0x04) LCD_D6=1; else LCD_D6=0;
    if(c & 0x02) LCD_D5=1; else LCD_D5=0;
    if(c & 0x01) LCD_D4=1; else LCD_D4=0;
    LCD_STROBE;    
    delay_us(40);
}
/*
 *     Clear and home the LCD
 */
void
lcd_clear(void)
{
    LCD_RS = 0;
    lcd_write(0x1);
    delay_ms(2);
}
/* write a string of chars to the LCD */
void
lcd_puts(const char * s)
{
    LCD_RS = 1;    // write characters
    while(*s) lcd_write(*s++);
}
/* write one character to the LCD */
void
lcd_putch(unsigned char c)
{
    LCD_RS = 1;    // write characters
    lcd_write(c);
}
/*
 * Go to the specified position
 */
void
lcd_goto(unsigned char pos,unsigned char line)
{
    LCD_RS = 0;
    if (line==0)
    lcd_write(0x80 + pos);
    else
    lcd_write(0x80 + pos+ 0x40);
}
    
/* initialise the LCD - put into 4 bit mode */
void
lcd_init(void)
{
    LCD_RS = 0;    // write control bytes
    delay_ms(15);// power on delay
    LCD_D4 = 1;    // init!    
    LCD_D5 = 1; //
    LCD_STROBE;    
    delay_ms(5);
    LCD_STROBE;    // init!    
    delay_us(100);
    LCD_STROBE;    // init!    
    delay_ms(5);
    LCD_D4 = 0;    // set 4 bit mode
    LCD_STROBE;    
    delay_us(40);
    
    lcd_write(0x28);// 4 bit mode, 1/16 duty, 5x8 font, 2lines
    lcd_write(0x0C);// display on
    lcd_write(0x06);// entry mode advance cursor
    lcd_write(0x01);// clear display and reset cursor
}
// Standard Input/Output functions
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
//PORTA=0x00;
//DDRA=0x00;
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=In Func0=In 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=T State0=T 
PORTD=0x00;
DDRD=0xFC;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
//OCR0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
        
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
lcd_init();
      
while (1)
      {  
      lcd_clear(); 
      lcd_goto(0,0);
      lcd_puts("Vh:") ; 
      itoa( b1  , buf); 
      lcd_puts(buf) ;      
      lcd_putch('V');  
      lcd_goto(8,0);
      lcd_puts("Vl:") ;
      itoa(b2  , buf); 
      lcd_puts(buf) ;  
      lcd_putch('V');     
      lcd_goto(0,1);
      lcd_puts("Freq.:") ;
      itoa(b3, buf); 
      lcd_puts(buf) ;  
      lcd_puts("Hz") ;      
      b1++;
      b2--;
      b3+=2;
      delay_ms(50);
      };
}

If you want to use library with other compilers or microcontrollers, just define pin locations correctly, basically just redefine these lines:

#define LCD_RS    PORTD.2    // Register select
#define LCD_EN    PORTD.3    // Enable
#define LCD_D4 PORTD.4    // Data bits
#define LCD_D5 PORTD.5    // Data bits
#define LCD_D6 PORTD.6    // Data bits
#define LCD_D7 PORTD.7    // Data bits
PORTD=0x00;
DDRD=0xFC;

More details about itoa function can be found in AVR ADC example where this function is used

You can download complete Codevision AVR project for control of 2x16 character LCD display from this link. Below is video showing how this example works on display in reality.