LCD Interfacing 4 Bit   
LCD is the most common way to let your controller speak its desires :-). So lets find out how can we make it happen, using only total of 7 pins from your microcontroller's GPIO. So LCD module will cost single port out of four...

Schematic Diagram -

>> This circuit consists of a Microcontroller and a LCD.

>>This LCD is operating with an 4-bit data bus. So totally 7 data lines are required (4 Data lines and 3 control lines).

>>The 4 bit data lines and 3 control lines are connected to the PORTB.

>> The EN line is called "Enable." This control line indicates to the LCD that we are sending it data. To send data to the LCD, the EN should be low (0) and then set the other two control lines and/or put data on the data bus. When the other lines are completely ready, bring EN high (1) and wait for the minimum amount of time required by the LCD datasheet (this varies from LCD to LCD), and end by bringing it low (0) again.

>> The RS line is the "Register Select" line. When RS is low (0), the data is to be treated as a command or special instruction (such as clear screen, position cursor, etc.). When RS is high (1), the data being sent is text data, which should be displayed on the screen. For example, to display the letter "T" on the screen we would set RS high.

>>The RW line is the "Read/Write" control line. When RW is low (0), the information on the data bus is being written to the LCD. When RW is high (1), the program is effectively querying (or reading) the LCD. Only one instruction ("Get LCD status") is a read command. All others are written commands so RW will almost always be low.

>>While using LCD in 4 bit data mode it saves 4 bits of our total GPIO lines, that’s why it is most commonly used. MSB of any data or commnad is sent first over 4 bits and then 4 LSB sent by shifting the data byte 4 times left.

Example program For 4 bit LCD interfacing with ATmega16
File name - LCD.h (to be included in main program)
Compiler - WinAVR / AVR GCC

#define lcd_port   PORTB //LCD connected to PORTB as shown above
#define LCD_RS     0×01 
#define LCD_RW     0×02 
#define LCD_EN     0×08 

void lcd_reset(void) 
	lcd_port = 0xFF;
	lcd_port = 0×30+LCD_EN; 
	lcd_port = 0×30; 
	lcd_port = 0×30+LCD_EN; 
	lcd_port = 0×30; 
	lcd_port = 0×30+LCD_EN; 
	lcd_port = 0×30; 
	lcd_port = 0×20+LCD_EN; 
	lcd_port = 0×20;

void lcd_cmd (char cmd) { lcd_port = (cmd & 0xF0)|LCD_EN; lcd_port = (cmd & 0xF0); lcd_port = ((cmd << 4) & 0xF0)|LCD_EN; lcd_port = ((cmd << 4) & 0xF0); _delay_ms(2); _delay_ms(2); }
void lcd_init (void) { lcd_reset(); // Call LCD reset lcd_cmd(0×28); // 4-bit mode – 2 line – 5×7 font. lcd_cmd(0×0C); // Display no cursor – no blink. lcd_cmd(0×06); // Automatic Increment – No Display shift. lcd_cmd(0×80); // Address DDRAM with 0 offset 80h. }
// Function to display single Character void lcd_data (unsigned char dat) { lcd_port = ((dat & 0xF0)|LCD_EN|LCD_RS); lcd_port = ((dat & 0xF0)|LCD_RS); lcd_port = (((dat << 4) & 0xF0)|LCD_EN|LCD_RS); lcd_port = (((dat << 4) & 0xF0)|LCD_RS); _delay_ms(2); _delay_ms(2); }
// Function to display a String void lcd_puts(char *a) { unsigned int i; for(i=0;a[i]!=0;i++) lcd_data(a[i]); }

File name - main.c (demo program for 4 bit mode LCD interfacing)
Compiler - WinAVR / AVR GCC


int main(void)
	lcd_cmd(0x01); // Clear screen 
  	lcd_cmd(0x80);  // Initially at first line
  	lcd_cmd(0xc0);  // Command to goto second line
  	lcd_puts("LCD 4 Bit"); 
  	while(1==1); // loop forever
  	return 0;
Best viewed at Firefox 1024x768 resolution