Thread: LCD 8 Bit to 4 displaying random letters.

  1. #1
    Registered User
    Join Date
    Oct 2019
    Posts
    6

    LCD 8 Bit to 4 displaying random letters.

    Hello,
    I have been given the task to modify my code to run in 4 bit rather than the origional 8 bit. I have tried changing the function command to reflect this but all that happens is the LCD displays random letters, im really stuck as to what else could need changing. The LCD is your bog standard 2 row 16 character one. I will attach my code below. Any help would be amazing. (Note that lcd.c is below main)

    Code:
    #include "lcd.h"
    
    
    int main(void)
    {
        initLCD();
        cmdLCD(LCD_LINE1);
        putLCD('H');
        putLCD('e');
        putLCD('l');
        putLCD('l');
        putLCD('o');
        putLCD(' ');
        putLCD('W');
        putLCD('o');
        putLCD('r');
        putLCD('l');
        putLCD('d');
        putLCD('!');
        putLCD(' ');
        putLCD(' ');
    
    
    
    
        while(1);
    }
    insert
    Code:
    
    #include "lcd.h"
    
    
    void lcd_delayus(unsigned int us)        //blocking delay for LCD, argument is approximate number of micro-seconds to delay
    {
        unsigned char i;
        while(us--)
        {
            for(i=0; i<SystemCoreClock/4000000; i++){__NOP();}
        }
    }
    
    
    void WaitLcdBusy(void)
    {
        set_LCD_bus_input();
        set_LCD_RW();
        clr_LCD_E();
        clr_LCD_RS();
        
        int port;
        do { 
            set_LCD_E();
            lcd_delayus(10);
            port= LCD_PORT->IDR&(1u << 7);
            clr_LCD_E();
        }
        while(port>0); 
        
        set_LCD_bus_output();
    }    
        //lcd_delayus(3000);        //3ms blocking delay
    
    
    void set_LCD_data(unsigned char d)
    {
        LCD_PORT->BSRR=(0xff<<(LCD_D0_pin+16));    //clear data lines
        LCD_PORT->BSRR=(d<<LCD_D0_pin);                    //put data on lines
    }
    
    
    void LCD_strobe(void)        //10us high pulse on LCD enable line
    {
        lcd_delayus(10);
        set_LCD_E();
        lcd_delayus(10);
        clr_LCD_E();
    }
    
    
    void cmdLCD(unsigned char cmd)        //sends a byte to the LCD control register
    {
        WaitLcdBusy();                //wait for LCD to be not busy
        clr_LCD_RS();                    //control command
        clr_LCD_RW();                    //write command
        set_LCD_data(cmd);        //set data on bus
        LCD_strobe();                    //apply command
    }
    
    
    void putLCD(unsigned char put)    //sends a char to the LCD display
    {
        WaitLcdBusy();                //wait for LCD to be not busy
        set_LCD_RS();                    //text command
        clr_LCD_RW();                    //write command
        set_LCD_data(put);        //set data on bus
        LCD_strobe();                    //apply command
    }
    
    
    void initLCD(void)
    {
            SystemCoreClockUpdate();
            RCC->AHB1ENR|=RCC_AHB1ENR_GPIODEN;    //enable LCD port clock
        
        
                //CONFIG LCD GPIO PINS
            LCD_PORT->MODER&=~(                    //clear pin direction settings
                (3u<<(2*LCD_RS_pin))
                |(3u<<(2*LCD_RW_pin))
                |(3u<<(2*LCD_E_pin))
                |(0xffff<<(2*LCD_D0_pin))
               &nbsp;);
        
        
        LCD_PORT->MODER|=(                //reset pin direction settings to digital outputs
                (1u<<(2*LCD_RS_pin))
                |(1u<<(2*LCD_RW_pin))
                |(1u<<(2*LCD_E_pin))
                |(0x5555<<(2*LCD_D0_pin))
           &nbsp;);
    
    
        
                //LCD INIT COMMANDS
        clr_LCD_RS();                    //all lines default low
        clr_LCD_RW();
        clr_LCD_E();
        
        lcd_delayus(25000);        //25ms startup delay
        cmdLCD(0x38);    //Function set=38: 2 Line, 8-bit, 5x7 dots  or 28 for 4 bit mode
        cmdLCD(0x0c);    //Display on, Cursor blinking command
        cmdLCD(0x01);    //Clear LCD
        cmdLCD(0x06);    //Entry mode, auto increment with no shift
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,490
    > for(i=0; i<SystemCoreClock/4000000; i++)...
    I would be suspicious of this doing anything useful given i is an unsigned char.
    Is the calculation even remotely within range?

    > &nbsp;);
    I would be suspicious of any code still containing HTML meta-character markup.

    > The LCD is your bog standard 2 row 16 character one.
    Regardless, find it's reference manual / data sheet online and make sure you fully understand it's initialisation sequence.

    > I have tried changing the function command to reflect this but all that happens is the LCD displays random letters
    Are they really random?
    Or is there some pattern, like all the l's in "Hello world" all come out as the same random letter?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2019
    Posts
    6
    Thank you for your response. The code works fine when all 8 of the bit wires are connected (and the setup is 8 bit), but when i change the set up to 4 bit on line 101 only nonsense is outputted. There appears to be no pattern at all - in fact when I hit re set the characters change.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,450
    Have you tried placing your "wait" between each of the commands. When placing a LCD into four bit mode the timing is quite critical, and waiting for the LCD busy flag is not always reliable for the setup.

  5. #5
    Registered User
    Join Date
    Oct 2019
    Posts
    6
    Good suggestion. That appears to of removed the rubbish letters and replaced the entire top row with solid black bars. Have you seen this before? Any ideas?

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,450
    It's been a while since I played with an LCD but if I remember correctly you have to repeat one of the commands twice (the first I think).

  7. #7
    Registered User
    Join Date
    Oct 2019
    Posts
    6
    LCD 8 Bit to 4 displaying random letters.-lcd-jpg

    I found the attached snippet from the data sheet. This appears to me to confirm that my tasks assignments are correct. (Or so i beleive).

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,490
    I would make damn sure lcd_delayus() is working as advertised.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Oct 2019
    Posts
    6
    Yea it is, as when running in 8 bit mode it works fine. Thanks for your help anyway.

  10. #10
    Registered User
    Join Date
    May 2010
    Posts
    4,450
    What type of system is this LCD connected to?

    It doesn't look like you're initializing the LCD properly for 4 bit operation. Re-check the data sheet for more information about proper initialization. Pay very strict attention to the timing specifications, they differ for different functions and also the first write to the LCD in any mode takes longer than normal and the Busy flag is usually not a reliable method for the first several bytes.

    It also doesn't look like you're properly writing to the LCD in 4 bit mode. You need to be writing two 4 bit nibbles for each character high bit first.

    By the way your code probably should look more like:
    Code:
    /*** 
    https://www.bipom.com/documents/appnotes/LCD%20Interfacing%20using%20HD44780%20Hitachi%20chipset%20compatible%20LCD.pdf
    
    Page 5
    Code Example for 4 - bit mode LCD initialization and displaying a message :
    ***/
    
    void InitLCD()
    {
        /* Wait a bit after power-up */
        delay(200);   // Note the timing!!!
        /* Initialize the LCD to 4-bit mode */
        WriteCtrl(3);
        delay(50);  // Note the timing!!!
        WriteCtrl(3); 
        delay(10);
        WriteCtrl(3); // Note the repetition of this command (three times)!!!!
        delay(10);
        WriteCtrl(2);
        delay(10);
        /* Function Set */
        WriteCtrl(2);
        delay(10);
        WriteCtrl(8);
        delay(10);
        /* Display OFF */
        WriteCtrl(0);
        delay(10);
        WriteCtrl(8);
        delay(10);
        /* Display ON */
        WriteCtrl(0);
        delay(10);
        WriteCtrl(0x0F);
        delay(10);
        /* Entry mode */
        WriteCtrl(0);
        delay(10);
        WriteCtrl(6);
        delay(10);
        /* Clear Screen */
        WriteCtrl(0);
        delay(10);
        WriteCtrl(1);
        delay(100);
        /* Cursor home */
        WriteCtrl(0);
        delay(10);
        WriteCtrl(2);
        delay(100);
    }
    void WriteLCD( unsigned char* message )
    {
        unsigned char i;
        for( i = 0; i < 20; i++ )
        {
            if( !message[i] )
                break;
            WriteData(message[i]);
        }
    }
    void WriteCtrl( unsigned char value )
    {
        clrbit(CTRL);
        WriteCommon( value );
    }
    void WriteData( unsigned char value )
    {
        setbit(CTRL);
        WriteCommon( value >> 4 );
        WriteCommon( value );
    }
    void WriteCommon( unsigned char value )
    {
        clrbit(READ);
        value = value & 0x0F;
        value = value << 4;
        P0 = P0 & 0x0F;
        P0 = P0 | value;
        setbit(STROBE);
        delay(1);
        clrbit(STROBE);
        setbit(READ);
        delay(1);
    }
    
    int main()
    {
        unsigned char i;
        /* Initialize the LCD as the very first thing */
        InitLCD();
        /* Write a simple message to the LCD */
        WriteLCD( "Hello" );
    }
    Note: This example is probably using a hardware timer to generate precise millisecond delays, you should see if your system can be setup with such a hardware delay.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Counting/displaying number of letters per line?
    By blindchicken11 in forum C Programming
    Replies: 3
    Last Post: 12-06-2011, 04:12 PM
  2. Generating random letters
    By ominub in forum C Programming
    Replies: 6
    Last Post: 04-29-2009, 01:12 AM
  3. Keyboard input without displaying letters.
    By explosive in forum C++ Programming
    Replies: 8
    Last Post: 12-06-2004, 11:24 AM
  4. Random letters
    By CAP in forum C Programming
    Replies: 19
    Last Post: 07-12-2002, 05:55 PM
  5. Random letters
    By Unregistered in forum C++ Programming
    Replies: 8
    Last Post: 06-09-2002, 11:35 PM

Tags for this Thread