[LCD] 4 Bit Mode not showing anything on the LCD

Discussion in 'Embedded Systems and Microcontrollers' started by Rafael Adel, Dec 30, 2015.

  1. Rafael Adel

    Thread Starter New Member

    Aug 7, 2015
    11
    0
    I'm trying to implement a function that displays the letter `c` on the LCD using 4-bit mode. But when I run the code on Proteus I get a blank lcd.
    I tried the code with 8 bit mode (without the bits manipulation) and works perfectly. So there's nothing wrong with lcd_send() and lcd_save() i guess.
    I know there's tons of libraries for that, but i'm trying to write it for learning purpose.

    Here's my code:
    Code (Text):
    1.  
    2. void init_lcd()
    3. {
    4.  //Setting DDRA and DDRC to output
    5.     struct conf con;
    6.     con.port_pointer = PINA_ADDR;
    7.     con.value= 0xff;
    8.     set_direction_port(con);
    9.  
    10.     con.port_pointer = PINC_ADDR;
    11.     con.value= 0xff;
    12.     set_direction_port(con);
    13.  
    14.     lcd_send_cmd(0x28);
    15.     lcd_send_cmd(0x0c);
    16. }
    17. void lcd_send_char(char c)
    18. {
    19.         // Sets direction to write
    20.     set_lcd_dir(0);
    21.        // Enables data register
    22.     set_control_reg(1);
    23.  
    24.     lcd_send(c & 0xf0);
    25.     lcd_save();
    26.     set_lcd_dir(0);
    27.     set_control_reg(1);
    28.     lcd_send((c & 0x0f) << 4);
    29.     lcd_save();
    30. }
    31.  
    32. void lcd_send(char c)
    33. {
    34.     struct conf con;
    35.     con.port_pointer = PINC_ADDR;
    36.     con.value= c;
    37.  
    38.     write_port(con);
    39. }
    40.  
    41. void lcd_save()
    42. {
    43.     //Saving
    44.     set_lcd_enable(0);
    45.     _delay_ms(1);
    46.     set_lcd_enable(1);
    47.     _delay_ms(1);
    48.     set_lcd_enable(0);
    49. }
    I will attach the code with proteus file in case you needed it.

    If there's any information needed, please tell me. Thanks.
     
    • lcd.zip
      File size:
      55.5 KB
      Views:
      2
    Last edited: Dec 30, 2015
  2. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005
    Where is you initialization function?
     
  3. Rafael Adel

    Thread Starter New Member

    Aug 7, 2015
    11
    0
    Added.
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,387
    1,605
    There are several very necessary delays you need to add to get the LCD up and running. There allow the display to do its power on reset, and also time to process the commands.

    These delays vary all over the place so you need to read the data sheet of the specific device you have.
     
  5. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005
    I am not seeing where you are telling the lcd it is 4 bit mode.

    This is what I do for the LCD library I use.

    Code (Text):
    1.  
    2.   LCD_nybble(0x02,0);  //Enable 4 bit mode
    3.    delay_ms(1);
    4.  
    5.    LCD_cmd(0b00101100);       //set 4-bit mode and 2 lines @ 5x7
    6.    delay_us(160);
    7.  
    And you need delays like Ernie mentioned unless it is in your other functions which you seem reluctant to post all of your relevant code for some reason.
     
  6. Rafael Adel

    Thread Starter New Member

    Aug 7, 2015
    11
    0
    Here in the init function:
    Code (Text):
    1.     lcd_send_cmd(0x28);
    2.  
    I've attached the whole project files.
     
  7. Rafael Adel

    Thread Starter New Member

    Aug 7, 2015
    11
    0
    So what're you saying is that it maybe a delay problem ? not a bit fiddling problem for instance ?
     
  8. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005
    I would have to analyze what a 0x28 does as I have not worked with LCDs for some time now. Just showing you what works for me. You can do with that what you want.

    And it might be helpful if you gave a bit more information when posting so others can help you.
     
  9. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005
    The delay in sending commands is extremely important in the LCD. And you can't just send your init routine at power up. I delay 40 ms before sending init data.
     
  10. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,387
    1,605
    Since this is a Proteus simulation it may work fine without delays, such is a limitation of simulation. It will not work on the real world hardware.

    If you use the same routine to send a character in either an 8 bit or a 4 bit mode then you are doing it wrong. 4 bit mode means you literally send the 8 bit character 4 bits at a time, in 2 separate transactions.

    Look, everyone who tries this gets stuck for some time, most make it thru anyway. The ones who get thru the fastest start with some example they read off the interwebs. Google is your friend here, try searching for "Proteus LCD example" and add in the processor you are using. I suspect someone else who did this and got it to work will have posted his code somewhere.
     
    absf likes this.
  11. dannyf

    Well-Known Member

    Sep 13, 2015
    1,806
    361
    That means the LCD isn't properly initialized - if you look at your init_lcd() routine vs. the datasheet, the errors are obvious.

    Embedded programming is easy in that you just need to code to the datasheet of the device that you are programming to / on. In this case, your code isn't even close to the datasheet.
     
    absf likes this.
  12. Rafael Adel

    Thread Starter New Member

    Aug 7, 2015
    11
    0
    Could you please give me a link for that datasheet ?
     
  13. dannyf

    Well-Known Member

    Sep 13, 2015
    1,806
    361
    Google is your best friend here.

    BTW, Proteus is very realistic. If you get your code working on Proteus, it has a great chance to work in the real world.
     
  14. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005
    I would not be so sure of that statement.
     
    ErnieM likes this.
  15. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005

    Believe it or not I was just looking at mine to upgrade an old project.

    As long as it is Hantonix based here.
     
    absf likes this.
  16. jpanhalt

    AAC Fanatic!

    Jan 18, 2008
    5,692
    901
    Here is assembly for the initialization:
    Code (ASM):
    1.  
    2. POR
    3. ;POR according to Hitachi datasheet.  NB: RB<0:3> are mapped to display lines
    4. ;DB<4:7>, in order.  Use PutNib for the POR unitl 4-bit mode is set.   A swapf
    5. ;is not needed in PutNib as the lower 4 bits of PORTB are sent first and only
    6. ;those bits are sent.
    7.  
    8.      DelayCy   (100*msecs)
    9.      movlw     0x03      
    10.      call      PutNib
    11.      DelayCy   (5*msecs)
    12.      movlw     0x03
    13.      call      PutNib
    14.      DelayCy   (1*msecs)
    15.      movlw     0x03
    16.      call      PutNib      
    17.      movlw     02           ;Function set: read as 0x20
    18.      call      PutNib         ;4-bit mode is now set, N & F not defined yet
    19.  
    20. ;LCD is now in 4-bitmode and 8-bit instructions and data are sent as two nibbles.
    21.  
    22.      movlw     0x28           ;Function set: 8 bits sent 4-bit mode
    23.      call      PutCmd         ;N & F are now defined
    24.      movlw     0x08           ;Display on/off control: display off
    25.      call      PutCmd    
    26.      DelayCy   (150*msecs)    ;blinks screen (optional)
    27.      DelayCy   (150*msecs)    ;blinks screen (optional)
    28.      movlw     0x01           ;Clear display: clears display
    29.      call      PutCmd    
    30.      DelayCy   (2*msecs)
    31.         movlw     0x06           ;Entry mode set: increment address (cursor)
    32.       call       PutCmd    
    33.       movlw     0x0C           ;Display on/off: display on/cursor off/blink off
    34.       call       PutCmd
    35.         return
    36.  
    Don't know if that helps. Here is a link to the Hitachi datasheet: https://www.sparkfun.com/datasheets/LCD/HD44780.pdf

    John

    Edit: That code was written before I started using the busy signal for timing. Once you enter 4-bit mode, using busy removes doubts about how long the delays should be.
     
    Last edited: Dec 30, 2015
  17. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,387
    1,605
    I would turn that statement around as such:
    "If you can't get your code working on Proteus, you have no chance it will work in the real world."

    Simulators cannot possibly cover all real world possibilities.
     
    spinnaker likes this.
  18. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,884
    1,005

    Op is programming in C.

    I have attached the code that I use in C. You will need to customize it.
     
  19. jpanhalt

    AAC Fanatic!

    Jan 18, 2008
    5,692
    901
    That was obvious, hence my comment. Nevertheless, converting the algorithm/sequence from Assembly to C should not be difficult. In fact, that is why I didn't include the code for PutCmd, etc. The OP was simply not following the datasheet.

    John
     
Loading...