LCD programming

Discussion in 'Programmer's Corner' started by andrew24, Jun 21, 2009.

  1. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    Hallo! i'm trying to send a text string to LCD for the first time. Could you check my code for any errors? Thanks :)

    Code ( (Unknown Language)):
    1. /LCD DATA BUS CONNECTED TO PORTD , 8 bit mode
    2. // RS connected to PB0, R/W to PB1, E to PB2
    3.  
    4. #include <avr/io.h>
    5. #include <util/delay.h>
    6. #include <string.h>
    7.  
    8.  
    9. void LCD_WAIT(void)
    10.  {
    11.  
    12.  DDRD=0; //Set all pins as inputs for reading busy flag
    13.  PORTB=0x00; // It's a read command
    14.  
    15.  // checking if the LCD  is still busy
    16.  while(!(PIND7&0b100000)){  
    17. _delay_loop_2(10);
    18. }
    19. }
    20.  
    21.  
    22. void LCD_SEND_COMMAND(void)
    23.  {
    24.  
    25.  DDRD=0xFF; //Set all pins as outputs for sending instruction
    26.  PORTB|=(1<<PORTB1);; // It's a write command
    27.  
    28.  PORTB|=(1<<PORTB2); //E=1
    29.  _delay_loop_2(1000);
    30.  PORTB&=0b1111011; // E=0
    31.  _delay_loop_2(1000);
    32.  
    33.  LCD_WAIT();
    34.  
    35.  DDRD=0XFF; //SET PORTD PINS AS OUTPUT
    36.  DDRB=0XFF; //SET PORTB PINS AS OUTPUT- FOR E,RW,RS
    37.  
    38.  }
    39.  
    40.  
    41.  
    42.  void LCD_INIT(void)
    43.  {
    44.  
    45.  // FUNCTION SET
    46.  
    47.  PORTD=0x38; //8 BIT INTERFACE,2 LINES,5*7 FONT
    48.  LCD_SEND_COMMAND();
    49.  
    50.  
    51.  // DISPLAY ON/OFF CONTROL
    52.  
    53.  PORTD=0x0E; //DISPLAY ON, CURSOR ON, BLINK OFF
    54.  LCD_SEND_COMMAND();
    55.  
    56.  
    57.  // DISPLAY ON/OFF CONTROL
    58.  
    59.  PORTD=0x06; // AUTOMATIC CURSOS POSITION INCREMENT
    60.  LCD_SEND_COMMAND();
    61.  
    62.  // CLEAR DISPLAY
    63.  PORTD=0x01; //CLAER DISPLAY & RETURN CURSOR HOME
    64.  LCD_SEND_COMMAND();
    65.  }
    66.  
    67.  
    68.  
    69. void LCD_WRITE(char TEXT[])
    70.  {
    71.  unsigned char i;
    72.  
    73. PORTB|=(1<<PORTB0);
    74.  
    75.  for(i=0;(i<32)&&(TEXT[i]!='\0');i++)
    76.  {
    77.  PORTD=TEXT[i];
    78.  LCD_SEND_COMMAND();
    79.  
    80.  }
    81.  }
    82.  
    83.  
    84. int main(void){
    85.  
    86.  LCD_INIT();
    87.  LCD_WRITE("Andrew");
    88.  }[/i][/i]
     
    Last edited: Jun 21, 2009
  2. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    One comment I would make is that your function "main" is defined to return an integer. I am surprised that you are able to get the program to compile without a return(0); statement.

    hgmjr
     
  3. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    My comments are based on the assumption that your LCD display is based on the Hitachi HD44780 LCD driver.

    My experience with LCD programming is that they are very picky about the initialization process. I seem to recall that a delay is required following power up to allow the LCD driver to complete its internal power up sequence. I don't see any delay being provided.

    hgmjr
     
  4. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    Yes,it's HD4478 :) should I provide a delay right after this line? " void LCD_INIT(void){ "
    thanks for correcting my mistakes!
     
    Last edited: Jun 21, 2009
  5. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    You may want to consider using the LCD.h and LCD.c routines that are included in the AVRSTUDIO/WINAVR package to bootstrap your LCD interface.

    hgmjr
     
  6. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    I'd rather write my own routine, i think the understanding comes when one succesfully makes something by himself :) However, I connected the LCD, loaded the code to the microcontroller, but nothing happened.. One strange thing is that if i connect LCD's VCC and VDD and also backlight's anode to the power supply there is no backlight, but if i leave VCC floating, the there is a backlight..
     
  7. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    You can at least use the LCD.c as a guide to assist you in constructing your own routine.

    hgmjr
     
  8. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    I will try that. Is there any simple way to scheck if the LCD is still stil alive? When connected to the power supply how it should behave? i found it to be very hot after my programming atempts :)
     
  9. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    The initialisation process for an LCD display is quite involved and easy to get wrong.
    This document tells you all you need to know. http://fab.cba.mit.edu/classes/MIT/863.05/classes/11_14/44780.pdf
    Take a look at pages 45/46 for the initialisation sequence and pay close attention to the time delays between instructions.

    I have found that when you power up an LCD without initialising it, it comes up in 1 line mode with the top line line showing all solid blocks but I suspect it could come up in any state.
     
  10. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    Thanks, AlexR, i read that datasheet. Why on page 45 do they recommend to initialise the function set 3 times?
     
  11. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    The honest answer is I don't know but I suspect that the first 2 times it is for the HD44780 chip reset sequence and the third time is to put it into 8 bit mode.

    In any case that data sheet is produced by Hitachi (the manufactures of the HD44780 chip) and if you follow their recommendations everything works as it should.
     
  12. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    I have programmed a couple of LCD modules and it is just as alexr has indicated. It is easy to err in performing the initialization sequence and if you don't get it right the LCD will not operate. The delays that are recommended in between the commands during the power up sequence are critical minimum delay times. They are needed for the HD44780 chip to take care of its internal set of registers. If you shorten these delays or leave them out altogether, the LCD will not operate or its operation will be irradic.

    Since this is your first LCD programming experience, I would recommend that you start by using the built-in function to verify that your LCD display is not damaged since you have stated that it is getting hot. Keep in mind that programming an LCD module is a challenge even for the seasoned programmer. Once you have convinced yourself that the LCD module is good, then you can try your hand at writing your own LCD interface program secure in the knowledge that if it does not work then you need to debug your code.

    hgmjr
     
  13. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    Thanks for all that helped me! I finaly made it to display my name.
    However there is one bug: when i send instruction to clear the screen and return the cursor home, and then try to display some text, lcd displays nothing, just blinks cursor. When i commented the clear screen instruction the text was displayed, but but screen is unclear from previos tests.
    How can i clear screen everytime i send something new to lcd, and at the same time display a text?
    thanks, Andrew
     
  14. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    A bit of a guess here but I suspect that you may not be giving the LCD time enough to clear its memory and return to readiness to except the next command you send it. I would recommend that you look into implementing the code needed to test the "busy" flag that is available from the LCD. This should eliminate your problem. If you test the "busy" flag and wait for LCD to return to the "not busy" state, things will work more consistently.

    hgmjr
     
  15. andrew24

    Thread Starter Active Member

    Aug 20, 2008
    76
    0
    You were right, that helped me! I have another question, about how to send a variable, or a number to an lcd. i wrote a function for that, but it doesn't work corectly: it was meant to split a number for e.g 245 to a separate digits (2,4,5) and assignd an ASCII value for them.

    void LCD_WRITE_CHAR(unsigned int charr[])
    {
    unsigned char i;

    for(i=0;i<sizeof(charr)-1;i++)
    {

    PORTB|=0x01; //RS low for writting data
    _delay_loop_1(1400/1000); // WAIT 140 ns

    if (charr==0) PORTD=48;
    else if (charr==1) PORTD=49;
    else if (charr==2) PORTD=50;
    else if (charr==3) PORTD=51;
    else if (charr==4) PORTD=52;
    else if (charr==5) PORTD=53;
    else if (charr==6) PORTD=54;
    else if (charr==7) PORTD=55;
    else if (charr==8) PORTD=56;
    else if (charr==9) PORTD=57;

    PORTB|=0x04; // Set E high
    _delay_loop_1(80/1000); // Wait 80ns
    PORTB=0x00; // Set E low
    _delay_loop_1(10/1000); // wait 10 ns

    }
    }
     
    Last edited: Jun 26, 2009
Loading...