+ Reply to Thread
Results 1 to 10 of 10

Thread: 4 Bit LCD interfacing (AVR).

  1. #1
    lord loh. Newbie
    Join Date
    Jan 2005
    Location
    India.
    Posts
    621

    Question 4 Bit LCD interfacing (AVR).

    I have been working for the past few days to interface a 16x2 LCD Module with an ATmega32 without success...

    My connections are as

    E -> D.7
    RS ->C.4
    RW ->C.5
    DB4->C.0
    DB5->C.1
    DB6->C.2
    DB7->C.3


    Here are my files.

    Where can I be going wrong?

    Please help. Thanks in advance.

    lcd.h
    Code:
    #define LCD_PORT PORTC
    #define LCD_BUSY 3
    #define LCD_CMD 4
    #define LCD_RW 5
    #define LCD_LED 6
    #define LCD_SEL 7
    
    #define LCDWord(data,cmd,rw) ((data)|(cmd<<LCD_CMD)|(rw<<LCD_RW)|(LCD_PORT&0x40))
    
    #define selectLCD (PORTD &= ~(1 <<7))
    #define unSelectLCD (PORTD |= (1<<7))
    #define ledOn sbi(LCD_PORT,LCD_LED)
    #define ledOff cbi(LCD_PORT,LCD_LED)
    
    void lcd_init(void);
    void lcd_writeCommand(unsigned char data);
    void lcd_writeData(unsigned char data);
    void lcdBusy(void);
    void clk(void);
    
    void clk(void)
    {
    	unSelectLCD;
    	_delay_us(5);
    	selectLCD;
    }
    
    void lcd_init(void)
    {
    	sbi(DDRD,7);
    	DDRC=0xff;			//PORT C -> Output.
    	selectLCD;			//clk ->Low
    			
    	LCD_PORT=LCDWord(0b0011,0,0);	//8bit interface
    		
    	clk();				//clk = high->low
    	_delay_ms(20);
    	
    	clk();
    	_delay_ms(20);
    
    	clk();
    	_delay_ms(20);
    
    	LCD_PORT=LCDWord(0b0010,0,0);	//4bit interface
    	
    	clk();
    	_delay_ms(20);
    
    	lcd_writeCommand(0b00101000);	//4 Bit 2 Line
    	lcd_writeCommand(0b00001110);	//Display ON Cursor On
    	lcd_writeCommand(0b00000110);	//Entry mode
    	lcd_writeCommand(0b00000001);	//ClearDisplay
    	lcd_writeCommand(0b00000010);	//Return Home
    	
    	
    }
    
    void lcd_writeCommand(unsigned char data)
    {
    	LCD_PORT=LCDWord(((data&0xF0)>>4),0,0);	//MSB
    	clk();
    	lcdBusy();
    	LCD_PORT=LCDWord((data&0x0F),0,0);	//LSB
    	clk();
    	lcdBusy();
    }
    
    void lcd_writeData(unsigned char data)
    {
    	LCD_PORT=LCDWord(((data&0xF0)>>4),1,0);	//MSB
    	clk();
    	lcdBusy();
    	LCD_PORT=LCDWord((data&0x0F),1,0);	//LSB
    	clk();
    	lcdBusy();
    }
    
    void lcdBusy(void)
    {
    	/*cbi(DDRC,LCD_BUSY);		//Make Bit 7 as i/p
    	unSelectLCD;			//EN->H
    	cbi(LCD_PORT,LCD_CMD);	//Command
    	sbi(LCD_PORT,LCD_RW);	//Read
    	while(1)
    	{
    		selectLCD;
    		unSelectLCD;
    		if bit_is_set(LCD_PORT,LCD_BUSY) break;
    	}
    	sbi(DDRC,LCD_BUSY);		//Make Bit 7 as o/p
    	*/
    	_delay_ms(20);
    }
    
    stdmacro.h
    Code:
    #define rotl(var) (((var&0x80)>>7)|(var<<1))
    #define sbi(port, bit) (port) |= (1 << (bit))
    #define cbi(port, bit) (port) &= ~(1 << (bit))
    
    lcdtest.c
    Code:
    #include <avr/io.h>
    #include <avr/wdt.h>
    
    #define F_CPU 1000000UL
    #include <util/delay.h>
    
    #include "stdmacro.h"
    #include "lcd.h"
    
    
    int main()
    {
    	wdt_disable();
    	_delay_ms(5);
    	lcd_init();
    	ledOn;
    	lcd_writeCommand(0x84);
    	lcd_writeData(0x45);
    	while(1)
    	return 0;
    }
    
    Bharath Bhushan Lohray.
    M.Sc. Electronics.


  2. #2
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,798

    Default

    You code is very confusing as you have unSelectLCD enabling the LCD and SelectLCD disabling it!! However, I think you problem is in your LCDBusy routine.

    Your lcdBusy needs to do,
    Set D7 as input, RW=1 and RS=0.
    Make Enable = 1,
    Wait for D7=0.
    Make Enable=0.

    Here is my code for a pic but the sequence is the same,
    Code:
    //wait for the LCD to finish last command.
    void WaitLCDBusy(void){
        LCD_TRIS_BUSY = 1;              //set pin to input
        LCD_RS = 0;                     //Command
        LCD_RW = 1;                     //We want to read
        LCD_E=1;                        //enable LCD interface
        while(LCD_BUSY);                //wait for busy to clear
        LCD_E=0;                        //disable LCD interface
        LCD_TRIS_BUSY = 0;              //restore pin to output
    }
    
    HTH,

    Mike.

  3. #3
    lord loh. Newbie
    Join Date
    Jan 2005
    Location
    India.
    Posts
    621

    Default

    my LCD Busy is just a delay of 20 ms. I have avoided it for the time being...
    Bharath Bhushan Lohray.
    M.Sc. Electronics.

  4. #4
    futz Excellent futz Excellent futz Excellent futz Excellent futz Excellent futz Excellent futz Excellent
    Join Date
    Sep 2007
    Location
    Vancouver, B.C.
    Posts
    1,980

    Default

    Quote Originally Posted by lord loh. View Post
    my LCD Busy is just a delay of 20 ms. I have avoided it for the time being...
    Don't avoid it! I did the exact same thing for a while. Then I finally implemented busy checking and it was easy, and makes your LCD code totally trouble free. Delays are only for when you really can't afford to lose that one MCU pin.

    Delays are always a pain. Every time you change MCU or clock speed the LCD won't work without a bunch of fooling around with the delays.

    There's some simple AVR LCD code on my site. See Dragon Rider 500 and ATMega88 and LCD.
    =========================
    Futz's Microcontrollers & Robotics
    =========================

  5. #5
    Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent Pommie Excellent
    Join Date
    Mar 2005
    Location
    Brisbane Australia
    Posts
    6,798

    Default

    Quote Originally Posted by lord loh. View Post
    my LCD Busy is just a delay of 20 ms. I have avoided it for the time being...
    So you have, my apologies, I missed that.

    With your AVR compiler, when you do,
    Code:
    int main()
    {
    	wdt_disable();
    	_delay_ms(5);
    	lcd_init();
    	ledOn;
    	lcd_writeCommand(0x84);
    	lcd_writeData(0x45);
    	while(1)
    	return 0;
    }
    
    Where does the return 0; go to? Maybe you intended to have a semicolon on the while statement. It is probably unrelated to your problem but I thought I would mention it anyway.

    Mike.

  6. #6
    lord loh. Newbie
    Join Date
    Jan 2005
    Location
    India.
    Posts
    621

    Default

    The return 0 is just a formality as there is a int main() and there has to be a ; for while... I guess I can do away eith teh while.... The compiler might generate an equivalent.
    Bharath Bhushan Lohray.
    M.Sc. Electronics.

  7. #7
    lord loh. Newbie
    Join Date
    Jan 2005
    Location
    India.
    Posts
    621

    Default

    Here I have re written the code.

    I still see only one dark line. No character appears. I am expecting one character at the 4th position of the first line 'E'.

    I still have not figured out what is wrong.

    Code:
    #include <avr/io.h>
    #include <avr/wdt.h>
    
    #define F_CPU 1000000UL
    #include <util/delay.h>
    
    #define LCD_PORT PORTC
    #define LCD_BUSY 3
    #define LCD_CMD 4
    #define LCD_RW 5
    #define LCD_LED 6
    #define LCD_SEL 7
    
    
    void lcd_init(void);
    void lcd_writeCommand(unsigned char);
    void lcd_writeData(unsigned char);
    
    int main()
    {
    	wdt_disable();
    	_delay_ms(5);
    	lcd_init();
    	lcd_writeCommand(0x84);
    	lcd_writeCommand(0x0E);
    	lcd_writeData(0x45);
    	return 0;
    }
    
    void lcd_init(void)
    {
    	DDRC=0xff;				//Port C is output
    	DDRD|=(1<<LCD_SEL);		//Port D.7 is Output
    	
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    
    	LCD_PORT&=~(1<<LCD_RW);	//Write
    	LCD_PORT&=~(1<<LCD_CMD);//Command
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=(LCD_PORT&0xF0)|0x03;//8 Bit interface.
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	_delay_ms(20);
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	_delay_ms(20);
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=(LCD_PORT&0xF0)|0x02;//4 Bit interface.
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    	
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	_delay_ms(20);			//4 Bit as 4 bit.
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    	
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=(LCD_PORT&0xF0)|0x08;//
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    
    	lcd_writeCommand(0x08);
    	lcd_writeCommand(0x01);
    	lcd_writeCommand(0x06);
    }
    
    void lcd_writeCommand(unsigned char data)
    {
    	LCD_PORT&=~(1<<LCD_RW);	//Write
    	LCD_PORT&=~(1<<LCD_CMD);//Command
    
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=((LCD_PORT&0xF0)|((data&0xF0)>>4));
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=((LCD_PORT&0xF0)|(data&0x0F));
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    }
    
    void lcd_writeData(unsigned char data)
    {
    	LCD_PORT&=~(1<<LCD_RW);	//Write
    	LCD_PORT|=(1<<LCD_CMD);	//ASCII
    
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=((LCD_PORT&0xF0)|((data&0xF0)>>4));
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    	PORTD|=(1<<LCD_SEL);	//E->High.
    	LCD_PORT=((LCD_PORT&0xF0)|(data&0x0F));
    	PORTD&=~(1<<LCD_SEL);	//E->Low.
    	_delay_ms(20);
    }
    
    Bharath Bhushan Lohray.
    M.Sc. Electronics.

  8. #8
    BeeBop Excellent BeeBop Excellent BeeBop Excellent BeeBop Excellent BeeBop Excellent BeeBop Excellent
    Join Date
    Dec 2005
    Location
    Vancouver Canada
    Posts
    1,192

    Default

    Quote Originally Posted by lord loh. View Post
    Here I have re written the code.

    I still see only one dark line. No character appears. I am expecting one character at the 4th position of the first line 'E'.

    I still have not figured out what is wrong.

    ... snip...
    This may not be helpful, I haven't looked closely at your code, but have you checked the contrast setting? If you are getting one line of dark squares on a two line display, then this could be what is happening.

  9. #9
    gualala Newbie
    Join Date
    Dec 2007
    Posts
    8

    Default

    Try putting the controller program in an infinite loop right before the return 0?

  10. #10
    lord loh. Newbie
    Join Date
    Jan 2005
    Location
    India.
    Posts
    621

    Default

    My contrast is okay... There is not even a ghost of a character....

    And I did have a while(); but I have removed it now...
    Bharath Bhushan Lohray.
    M.Sc. Electronics.

+ Reply to Thread

Similar Threads

  1. Pic interfacing with RTC
    By thunderboympm in forum Micro Controllers
    Replies: 4
    Latest: 20th September 2007, 05:59 PM
  2. Regarding LCD interfacing
    By husakhalid in forum Micro Controllers
    Replies: 1
    Latest: 24th May 2006, 08:13 AM
  3. RS 232 Interfacing with PIC
    By dreamproject in forum Electronic Projects Design/Ideas/Reviews
    Replies: 5
    Latest: 11th May 2006, 11:04 PM
  4. INTERFACING WITH C
    By aibelectronics in forum Electronic Projects Design/Ideas/Reviews
    Replies: 16
    Latest: 5th August 2005, 03:40 PM
  5. Need help in interfacing......
    By superpratyk in forum Micro Controllers
    Replies: 0
    Latest: 23rd January 2004, 02:00 AM

Tags for this Thread