A basic HD44780 LCD driver for AVR

Microcontroller Topics
Post Reply
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

A basic HD44780 LCD driver for AVR

Post by Herath » Sun Jul 31, 2011 12:47 am

This is a HD44780 character LCD driver I am writing. It is a very basic one. Writing commands, setting DDRAM address, writing data functions has been tested ONLY in a simulator. Busy flag reading cannot be tested on the simulator. I am still waiting for my development board. :)

I have commented on delay routines, otherwise it will not work with the simulator.

Code: Select all

#ifndef HD44780_H
#define HD44780_H

#include<avr/io.h>
#ifndef F_CPU
#define F_CPU 12000000
#endif
#include<util/delay.h>

#define CLEAR_DISPLAY 0b00000001
#define RETURN_HOME   0b00000010
#define DISPLAY_ON    0b00001100
#define DISPLAY_OFF   0b00001000
#define DIS_ON_CUR_ON_BLNK_OFF     0b00001110
#define DIS_ON_CUR_OFF_BLNK_OFF    0b00001100
#define DIS_ON_CUR_ON_BLNK_ON      0b00001111
#define DIS_ON_CUR_ON_BLNK_OFF     0b00001110
#define DIS_FUNC_SET               0b00111000 //8bit data, 2 lines, 5x10 dots

#define SET_E_PIN (PORTD |=(1<<3))
#define CLR_E_PIN (PORTD &=~(1<<3))
#define SET_RW_PIN (PORTD |=(1<<2))
#define CLR_RW_PIN (PORTD &=~(1<<2))
#define SET_RS_PIN (PORTD |=(1<<1))
#define CLR_RS_PIN (PORTD &=~(1<<1))
#define LCD_PORT PORTB

	extern void init_HD44780();
	extern void write_HD44780_Command(unsigned char cmd);
	extern void write_HD44780_DataAt(unsigned char address, char* data);
	extern void write_HD44780_Data(char* data);
	extern void set_HD44780_DDRAM_Address(unsigned char address);
	short LCDBusy();

#endif

Code: Select all

#include "hd44780.h"

void init_HD44780(){
	DDRB=0xFF;//All pins output
	DDRD=0xFF;
	
//	while(!LCDBusy());
	write_HD44780_Command(CLEAR_DISPLAY);
//	while(!LCDBusy());
	write_HD44780_Command(DIS_ON_CUR_ON_BLNK_ON);
//	while(!LCDBusy());
	write_HD44780_Command(DIS_FUNC_SET);
}

void write_HD44780_Command(unsigned char cmd){
	LCD_PORT=0x0;
	LCD_PORT|=cmd;
	CLR_RW_PIN;
	CLR_RS_PIN;
	CLR_E_PIN;	
	SET_E_PIN;
//	_delay_us(1);// wait
	CLR_E_PIN;
//	_delay_ms(5);
}

void write_HD44780_DataAt(unsigned char address,char* data){
	set_HD44780_DDRAM_Address(address);
	write_HD44780_Data(data);
}

void write_HD44780_Data(char* data){
	SET_RS_PIN;
	CLR_RW_PIN;
	CLR_E_PIN;
	while(*data){
//		while(!LCDBusy());
		LCD_PORT=0x0;
		LCD_PORT=*data;
		SET_E_PIN;
//		_delay_us(1);
		CLR_E_PIN;
//		_delay_us(200);
		data++;
	}
}

void set_HD44780_DDRAM_Address(unsigned char address){
	CLR_RS_PIN;//select IR
	CLR_RW_PIN;//Going to write
	LCD_PORT=0x0;
	LCD_PORT|=(1<<7); //|=0b10000000
	//Now set address
	LCD_PORT|=address;
	CLR_E_PIN;
	//_delay_us(2);
	SET_E_PIN;
//	_delay_us(2);
	CLR_E_PIN;
//	_delay_ms(5);

}
short LCDBusy(){
	SET_RW_PIN;
	CLR_RS_PIN;
	SET_E_PIN;
	_delay_us(10);
	if(LCD_PORT & 0x80) {// PIN 7 high
		CLR_E_PIN;
		CLR_RW_PIN;
		return 1;
	}else{
		CLR_E_PIN;
		CLR_RW_PIN;
		return 0;
	}
}
If there is something odd in here, please let me know. :D .
Thanks.
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: A basic HD44780 LCD driver for AVR

Post by Neo » Sun Jul 31, 2011 3:23 pm

Excellent post. I have a modified version which can address rows and columns separately. But I guess it can be easily figured out with this one.

REP+ ;)
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

Re: A basic HD44780 LCD driver for AVR

Post by Herath » Sun Jul 31, 2011 9:29 pm

How to access columns and rows seperately?. Is it like having a procedure writeData(short column_no, short row_no, char* data) ?. That seems nice. :)

I wrote this by my self after reading the HD44780 datasheet. So I am still to test this on live hardware. Most of the already available libraries are bloated ones.
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: A basic HD44780 LCD driver for AVR

Post by Neo » Sun Jul 31, 2011 9:37 pm

The reason I didn't put was because the codes are bit incompatible. I guess you'll be able to change it accordingly.

Code: Select all

// lcd_out will display the content with the given coordinates
void lcd_out (unsigned char y, unsigned char x, const char *msg){

	unsigned char address;

	switch (y) {
		case 1:
			address = 0x80;
			break;
		case 2:
			address = 0xc0;
			break;
		case 3:
			address = 0x94;
			break;
		case 4:
			address = 0xd4;
			break;
	}

	address += x-1;

	LCD_RS = 0;
	lcd_write(address);

	// Write characters
	LCD_RS = 1;
	while (*msg){
		lcd_write (*msg++);
	}
}
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

Re: A basic HD44780 LCD driver for AVR

Post by Herath » Sun Jul 31, 2011 9:54 pm

Looks like y is the row number. And LCD is a 4 row one. My LCD is having 16x2.
0x0 .... 0xF
0x40....0x4F

Anyway, I will try changing the code for my LCD.

Code: Select all

    // lcd_out will display the content with the given coordinates
    void lcd_out (unsigned char y, unsigned char x, const char *msg){
     
            unsigned char address;
     
            switch (y) {
                    case 1:
                            address = 0x80; //0b10000000
                            break;
                    case 2:
                            address = 0xC0;//0b11000000 (0x80+0x40)
                            break;
            }
     
            address += x-1;
     
            LCD_RS = 0;
            lcd_write(address);// Changing these require changing my set_HD44780_DDRAM_Address changed. And finally most of the code :D
     
            // Write characters
            LCD_RS = 1;
            while (*msg){
                    lcd_write (*msg++);
            }
    }
     

Thanks
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: A basic HD44780 LCD driver for AVR

Post by Neo » Sun Jul 31, 2011 10:22 pm

Looks like y is the row number.
Exactly.
And LCD is a 4 row one. My LCD is having 16x2
That won't be a problem. Addresses are same for this chip. I guess I have one 16x2 in my store. If you find any trouble I'll try my best to discover it ;)
User avatar
Herath
Major
Major
Posts: 417
Joined: Thu Aug 05, 2010 7:09 pm

Re: A basic HD44780 LCD driver for AVR

Post by Herath » Mon Aug 01, 2011 2:00 am

Code: Select all

void write_HD44780_DataAtColRow(unsigned char y,unsigned char x,char* data){
	unsigned char address=0;
	switch(y){
		case 1:
			address=0x80;
			break;
		case 2:
			address=0xC0;
			break;
	}

	address+=x-1;
	write_HD44780_DataAt(address,data);

}


void write_HD44780_DataAt(unsigned char address,char* data){
	set_HD44780_DDRAM_Address(address);
	write_HD44780_Data(data);
}
Did not want to change anything else. Only to write this function. I already had the function to write data at a give memory location. I only figured it out after opening it in AVR Studio to work on it for few minutes. :)
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: A basic HD44780 LCD driver for AVR

Post by Neo » Mon Aug 01, 2011 10:54 am

Excellent ;)
Post Reply

Return to “Microcontrollers”