AVR LCD is blank after code change

avrcharacter-lcd

Following is my code

#include <avr/io.h>
#include <util/delay.h>

#define Delay_ms(x) _delay_ms(x)
#define RS   1       //PC0
#define RW   1       //PC1
#define EN   2       //PC2


void lcd_cmnd(unsigned char);
void lcd_data(unsigned char dta);


int main()
{
    DDRC=0xff;
    DDRD=0xff;
    lcd_cmnd(0x38);          //sets 8-bit interacing
    Delay_ms(1);


    lcd_cmnd(0x0e);           //display on
    Delay_ms(1);
    lcd_cmnd(0x08);           //display off
    Delay_ms(1);
    lcd_cmnd(0x01);        //clears screen
    Delay_ms(1);



    lcd_cmnd(0b00000000);
    lcd_cmnd(0x06); //Entry Mode, Increment cursor position, No display shift

    lcd_data('N');
    Delay_ms(250);

    lcd_data('a');
    Delay_ms(25);
    lcd_data('s');
    Delay_ms(25);
    lcd_data('i');
    Delay_ms(25);
    lcd_data('r');
    Delay_ms(25);
return 0;
}
void lcd_cmnd(unsigned char cmd)
{
    PORTD=cmd;
    PORTC=(0<<RS);                //command mode   PC0=RS(low)
    PORTC|=(0<<RW);                // read mode  PC1=RW
    PORTC=(1<<EN);                 // enable high   PC2=EN
    Delay_ms(1);
    PORTC=(0<<EN);                 //enable low
    Delay_ms(50);
}

void lcd_data(unsigned char dta)
{

    PORTC|=(0<<RW);              //PC1=RW (low)
    PORTC|=(1<<0);               //DATA mode   PC0=RS
    PORTD=dta;
    PORTC=(1<<EN);                //enable high   PC2=EN


    Delay_ms(1);
    PORTC=(0<<EN);                //enable low
    Delay_ms(50);
}

It executes well, the simulation in proteus runs but the cursor just blinks and nothing is displayed. I don't know why.

Following is other code which runs and displays on the LCD "Hello World!"

#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <stdio.h>

//Define functions
//==========================================================
void io_init(void);                         //Initializes IO
void send_nibble(unsigned char __rs, unsigned char __data);

//==========================================================

int main (void)
{
    io_init();

   _delay_ms(15);
   send_nibble(0,0b0010);   //Set to 4 bit operation (note: 1 nibble operation)
   _delay_ms(5);

   send_nibble(0,0b0010);   //Function set, 4 bit
   send_nibble(0,0x08);     //display off, cursor off

   send_nibble(0,0b0000);
   send_nibble(0,0b1111);   //Display ON, Cursor On, Cursor Blinking

   send_nibble(0,0b0000);
   send_nibble(0,0b0001);   //Clear Display

   send_nibble(0,0b0000);
   send_nibble(0,0x06); //Entry Mode, Increment cursor position, No display shift

   send_nibble(1,0b0100);  //H
   send_nibble(1,0b1000);

   send_nibble(1,0b0110);  //e
   send_nibble(1,0b0101);

   send_nibble(1,0b0110);  //l
   send_nibble(1,0b1100);

   send_nibble(1,0b0110);  //l
   send_nibble(1,0b1100);

   send_nibble(1,0b0110);  //o
   send_nibble(1,0b1111);

   send_nibble(1,0b0010);  //Space
   send_nibble(1,0b0000);

   send_nibble(1,0b0101);  //w
   send_nibble(1,0b0111);

   send_nibble(1,0b0110);  //o
   send_nibble(1,0b1111);

   send_nibble(1,0b0111);  //r
   send_nibble(1,0b0010);

   send_nibble(1,0b0110);  //l
   send_nibble(1,0b1100);

   send_nibble(1,0b0110);  //d
   send_nibble(1,0b0100);

    return(0);
}

void io_init (void)
{
    /*
    PC 7: N/A
    PC 6: Reset
    PC 5: Enable
    PC 4: Register Select
    PC 3: Data 7
    PC 2: Data 6
    PC 1: Data 5
    PC 0: Data 4
    */

    DDRC = 0b00111111;  //63
}

void send_nibble(unsigned char __rs, unsigned char __data)
{
   PORTC = (__rs<<4) | __data | 0b00100000;      // Set RS &amp; Data. Set EN=High
   _delay_ms(1);
   PORTC = (__rs<<4) | __data;                   // Set RS &amp; Data. Set EN=Low
   _delay_ms(1);
}

I tried to proceed in the same order but in vain. I am stuck in learning the LCD programming for last 10 days. Any healthy and effective help is appreciated in advance!

Best Answer

Time to elaborate on my original comment...

You seem to be misunderstanding the part that the left shift operator (<<) the bitwise OR operator (|) play in setting bits. You can use the OR operator to set a bit to 1, but you cannot use it to reset a bit to 0. For example, in your code:

PORTC|=(0<<RW);                // read mode  PC1=RW

...you seem to be trying to reset the RW bit in PORTC to 0, but that is not what will happen with the above code. Since RW is defined as 1, 0<<1 will be compiled as "0 shifted left by 1 bit" (i.e. multiplied by 2) which is still just 0. Then you OR that 0 to the contents of PORTC resulting in no change to PORTC. That is, if PORTC bit 1 was on, it will still be on after the above is executed.

Assuming that what you really want to do is reset bit 1 (RW) of PORTC to 0 leaving all others the same, then that can be done by using the AND operator:

PORTC &= (255 - (1<<RW));

Personally, given the confusion this is causing you, I would recommend simply defining and using RW (and other bits) as follows:

//     Bit:  76543210
#define RS 0b00000001
#define RW 0b00000010
#define EN 0b00000100

PORTC |= RW;            // Turn on the RW bit
PORTC &= 255 - RW;      // Turn off the RW bit

To me that is clearer anyway. Alternatively, if you really want to work with bit position numbers, you could hide the bit-level acrobatics in a macro as follows:

#define biton(port,bitnum) port |= (1 << bitnum)
#define bitoff(port,bitnum) port &= 255 - (1 << bitnum)

biton(PORTC,RW);
bitoff(PORTC,RW);
Related Topic