Search code examples
avrlcd

lcd interfacing with atmega16


I tried interfacing lcd with atmega16 my lcd is jhd 162A.I have attached code as well as schematic.whenever I connect the appropriate pins only black spots are seen, not what i intended to display.I couldnt what my problem was.I have also attached schematic.!

#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 8000000L

#define lcd_data    PORTC
#define control     PORTB
#define rs          PB2
#define rw          PB1
#define en          PB0

void lcd_init (void);
void lcd_command(unsigned char cmd);
void lcd_write(unsigned char data);
void lcd_string(unsigned char *str);
void dis_cmd(char cmd_value);
void dis_write(unsigned char data);

int main()
{
    DDRB = 0xFF;
    DDRC = 0xFF;

    lcd_init();
    _delay_ms(50);

    _delay_ms(1);
    lcd_str("PROGRAMMING");
    _delay_ms(50);
    dis_cmd(0xc0);
    lcd_str("IS FUN");
     return 0;
}

void lcd_init (void)
{
    dis_cmd(0x02); //initialises lcd  on 4 bits mode
    _delay_ms(1);
    dis_cmd(0x28); //initialises lcd to use 2 line and 5*7 matrix ie 16*2 lcd on 8 bits
    _delay_ms(1);
    dis_cmd(0x01);//clears lcd screen
    _delay_ms(1);
    dis_cmd(0x0E);//display ON cursor ON
    _delay_ms(1);
    dis_cmd(0x80);//cursor is set on the 1st line
    _delay_ms(1);
    return;

}

void lcd_command(unsigned char cmd)
{
    lcd_data =cmd;
    control = (0<<rs)| (0<<rw) | (1<<en); // setting rs to 0 is command mode when rw=0 write mode
    _delay_ms(1);
    control = (0<<rs)| (0<<rw) | (0<<en);
    _delay_ms(50);

    // 2ta control command is used for the high to low transition of enable as the code works on the falling 
    // edge of the enable en
    return;
}

void lcd_write(unsigned char data)
{
    lcd_data= data;
    control = (1<<rs)| (0<<rw) | (1<<en); // setting rs to 0 is command mode when rw=0 write mode
    _delay_ms(1);
    control = (1<<rs)| (0<<rw) | (0<<en);
    _delay_ms(50);
    return;
}

void dis_write(unsigned char data)
{
    char data1;

    data1 = data & 0xF0;        //mask lower nibble because PA4-PA7 pins are used. 
    lcd_write(data1);


    data1 = ((data<<4) & 0xF0); //shift 4-bit and mask
    lcd_write(data1);

    return;
                // send to LCD

}
void lcd_str(unsigned char *str)
{
    int i = 0;
    while(str[i] != '\0')
    {
        dis_write(str[i]);
        i++;

    }
    return;

}
void dis_cmd(char cmd_value)
{
    char cmd_value1;

    cmd_value1 = cmd_value & 0xF0;      //mask lower nibble because PB4-PA7 pins are used. 
    lcd_command(cmd_value1);            // send to LCD

    cmd_value1 = ((cmd_value<<4) & 0xF0);   //shift 4-bit and mask
    lcd_command(cmd_value1);            // send to LCD
}

Solution

  • I think you are not performing the required init sequence. In lcd_init() you start by sending the function set.

    However, the display awaits a sequence before that like this:

    enter image description here

    I am not sure how this is handled using 4-bit interface, but i think thats why DB3-0 are "don't care". You probably just have to apply DB7-4 on your 4-bit bus (read the datasheet).

    I would wait for several hundred milliseconds on startup to make sure Vcc is stable. Then follow the reset sequence with relaxed timing like

    PowerOn
    Wait 200ms
    Send Instruction
    Wait 20ms
    Send Instruction
    Wait 5ms
    Send Instruction
    Wait 5ms
    Send Function Set
    ...

    Since you are not polling the busy flag, I would wait at least 1ms between all following instructions.