1
\$\begingroup\$

I try writing "NO" in the LCD using 4-bit mode. So, I programmed the AT89S52 to send the upper nibble first to the last 4 data inputs of the LCD. I used AND operation to eliminate the lower nibble. Afterwards, I cleared the RS bit and send a HIGH-TO-LOW enable pulse. The same code for the lower nibble but I added Swapping the nibbles of the data byte. The problem is that the LCD don't show anything. I uploaded the following assembly code to the AT89S52:


THE CODE AND THE CIRCUIT HAVE BEEN CHANGED

                ORG 00H
                RS BIT P2.7
                E BIT P2.6
                MOV SP, #25H
                MOV P1, #00H
                MOV P2, #00H
                MOV TMOD, #01H
;;;;;;;;;;;;;;;;;;;;;;;;;;;COMMANDS;;;;;;;;;;;;;;;;;;;;;;;;;;;
                MOV R1, #0C8H
                ACALL DELAY_MS
                
                MOV R0, #30H            ;8-BIT INITIALIZATION
                ACALL CMD
                MOV R1, #04H            ; 4MS DELAY
                ACALL DELAY_MS
                
                MOV R0, #30H            ;8-BIT INITIALIZATION
                ACALL CMD
                MOV R1, #0FH            ;150 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #30H            ;8-BIT INITIALIZATION
                ACALL CMD
                MOV R1, #05H            ;50 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #20H            ;4-BIT WITH 1 LINE INITIALIZATION
                ACALL CMD
                MOV R1, #05H            ;50 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #28H            ;4-BIT MODE OF LCD INITIALIZATION
                ACALL CMD               
                MOV R1, #05H            ;50 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #08H            ;DISPLAY OFF, CURSOR OFF
                ACALL CMD               
                MOV R1, #05H            ;50 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #06H            ;ENTRY MODE
                ACALL CMD               
                MOV R1, #05H            ;50 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #0CH            ;DISPLAY ON, CURSOR OFF
                ACALL CMD               
                MOV R1, #05H            ;50 MICROSECONDS DELAY
                ACALL DELAY_US
                
                MOV R0, #01H            ;CLEAR LCD
                ACALL CMD
                MOV R1, #02H            ;2 MS DELAY
                ACALL DELAY_MS
                
                MOV R0, #02H            ;HOME CURSOR
                ACALL CMD
                MOV R1, #02H            ;2 MS DELAY
                ACALL DELAY_MS
                
;;;;;;;;;;;;;;;;;;;;;;;;;;;PRINTING;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;               
                
                MOV R0, #'N'
                ACALL PRNT  
                ACALL DELAY_MS
                MOV R0, #'O'
                ACALL PRNT
                ACALL DELAY_MS
                
;;;;;;;;;;;;;;;;;;;;;;;;;;;NO LOOPING;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;               
                
HERE:           SJMP HERE

;;;;;;;;;;;;;;;;;;;;;;;;;;;COMMAND FUNCTION;;;;;;;;;;;;;;;;;;;;;;;;;;

CMD:            
;SENDING THE UPPER NIBBLE
                MOV A, R0
                ANL A, #0F0H
                MOV P1, A
                
                CLR RS                  ;COMMAND MODE
                SETB E
                ACALL DELAY_MS
                CLR E
                ACALL DELAY_MS
;SENDING THE LOWER NIBBLE
                MOV A, R0
                ANL A, #0FH
                SWAP A
                MOV P1, A
                CLR RS
                SETB E
                ACALL DELAY_MS
                CLR E
                ACALL DELAY_MS
                RET
                
;;;;;;;;;;;;;;;;;;;;;;;;;;;PRINT FUNCTION;;;;;;;;;;;;;;;;;;;;;;;;;;;                
                
PRNT:
;SENDING THE UPPER NIBBLE
                MOV A, R0
                ANL A, #0F0H
                MOV P1, A
                
                SETB RS                 ;DATA MODE
                SETB E
                ACALL DELAY_MS
                CLR E
                ACALL DELAY_MS
;SENDING THE LOWER NIBBLE
                MOV A, R0
                ANL A, #0FH
                SWAP A
                MOV P1, A
                SETB RS
                SETB E
                ACALL DELAY_MS
                CLR E
                ACALL DELAY_MS
                RET
                
;;;;;;;;;;;;;;;;;;;;;;;;;;;;DELAY FUNCTION;;;;;;;;;;;;;;;;;;;;;;;;;;                
                
DELAY_MS:           
                MOV TH0, #0F8H
                MOV TL0, #30H
                SETB TR0
LOOP:           JNB TF0, LOOP
                CLR TR0
                CLR TF0
                DJNZ R1, DELAY_MS
                RET
                
                
                
DELAY_US:       MOV TH0, #0FFH
                MOV TL0, #0ECH
                SETB TR0
LOOP1:          JNB TF0, LOOP1
                CLR TR0
                CLR TF0
                DJNZ R1, DELAY_US
                RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                
                
                END

This is the circuit of the LCD:enter image description here enter image description here

\$\endgroup\$
10
  • \$\begingroup\$ Those two symbols are valid ascii characters for 11010000 and 11100100 \$\endgroup\$ – James Jun 12 at 18:11
  • \$\begingroup\$ @James According to which datasheet/manual? The glyph with four horizontal stripes is either not 11010000 or the LCD has a non-standard font ROM. \$\endgroup\$ – Justme Jun 12 at 18:39
  • \$\begingroup\$ @Justme I have a single sheet of paper here which details the LCD character set, printed it off from somewhere years ago. It says "Matrix Multimedia LCD Display" on it. \$\endgroup\$ – James Jun 12 at 18:49
  • \$\begingroup\$ Don't know if it's having any effect on your results but the R/W pin on the LCD should be tied low to ground. - Oh but looking at the photo it looks like it is already tied to 0V \$\endgroup\$ – James Jun 12 at 19:14
  • \$\begingroup\$ The LCD draw these characters. After a while , the LCD is cleared. I pressed reset button many times and the LCD wrote "NO" what is the problem ?? \$\endgroup\$ – Kiroloes Amir Jun 12 at 19:56
1
\$\begingroup\$

It doesn't look like you're delaying long enough between commands:

           ;DELAY FUNCTION             
            
            DELAY:          MOV R1, #20H
            LOOP0:          NOP
            DJNZ R1, LOOP0  
            RET

Have a look at the delays used in this HD44780 code:

void    LCD_Init_Display(void)
    {
    __delay_ms(200);
    LCD_RW = 0;        //Set for write
    __delay_ms(5);                     // was 20
    LCD_Write_Command( 0b00110000);        //Function set 8 bit
    __delay_ms(6);                        //Need at least 4.1 mSec
    LCD_Write_Command( 0b00110000 );    //Function set 8 bit
    __delay_us(150);                    //Need at least 100 uSec
    LCD_Write_Command( 0b00110000 );    //Function set 8 bit
    __delay_us(50);
            //0 0 1 DL N F x x    ;DL: 1=8Bit 0=4Bit, N: 1=2Line 0=1Line, F: 1=10Dot 0=8Dot
    LCD_Write_Command( 0b00111000 );    //8 bit Function set 2 lines, 5x8 dots
    __delay_us(50);
    LCD_Write_Command( 0b00001000 );    //Display off
    __delay_us(50);
    LCD_Write_Command( 0b00000001 );        //Display clear
    __delay_ms(2);
    LCD_Write_Command( 0b00000110 );    //Entry mode set, <1> 1=incr, <0> 0=no shift
    __delay_us(50);
    LCD_Write_Command( 0b00010100 );    //Shift cursor right
    __delay_us(50);
    LCD_Write_Command( 0b00000010    );        //Cursor home
    __delay_ms(2);
        // Cursor is underline, Blink flashes character ;Display ON/OFF, Cursor OFF, Blink OFF
    LCD_Write_Command( 0b00001100 );
    __delay_ms(20);                        //long delay
    }

Source: https://www.microchip.com/forums/m1023133.aspx

The function __delay_us() delays for the specified number of microseconds and __delay_ms() delays for the specified number of milliseconds.

Note that the delays are at least 50 microseconds and some are in the millisecond range.

Note the initial 200 millisecond delay at the start of the LCD_Init_Display routine... The reason for this is that at power-up the HD44780 can take 10 milliseconds to initialize itself after the power rises to 4.5V.

\$\endgroup\$
2
  • \$\begingroup\$ Had a similar problem - adding the 20ms delay after Write_Command got it working in my case. It seems rare that reading LCD status is used - all the code I've seen uses this technique of write-and-delay. This may not be the only problem (see @justme) \$\endgroup\$ – glen_geek Jun 12 at 16:25
  • \$\begingroup\$ If the powerup reset delay before MCU starts to execute is large enough, the 4-bit mode entering gets fixed, and the display clear command is removed as it takes milliseconds, and char writing fixed, I am quite sure the delays are long enough for delays between standard commands. \$\endgroup\$ – Justme Jun 12 at 17:06
1
\$\begingroup\$

This is the initialisation sequence I have used some time ago with success. You'll need to create the correct delays between sending each byte/nibble.

3Xh - Display in 8 bit mode

3Xh - Display in 8 bit mode

3Xh - Display in 8 bit mode

2Xh - This byte, sent whilst display is in 8 bit mode, changes display to 4 bit mode.

28h - Set for two lines and 5x7. Display in 4 bit mode.

08h - Display off

06h - Set so cursor address is incremented

0Ch - Display on, cursor off, blink off

01h - Clear display, home cursor

02h - Home cursor

Initialisation Flowchart

\$\endgroup\$
0
\$\begingroup\$

The initialization sequence to go to 4-bit mode is wrong and the display will be out of sync forever.

The display boots into 8-bit mode, so when the first command 28h is sent as two nibbles 2h and 8h, the display understands the first nibble sent as 8-bit command 2Fh which sets the display into 4-bit mode, so the second nibble is understood by the display as first nibble of a command 8h in 4-bit mode.

The printing function also manages to clear RS bit low when the second nibble is updated to port P1.

\$\endgroup\$
5
  • \$\begingroup\$ I've added 0x20 command to the LCD, changed the bits of RS and E to P2.0 and P2.1 and changed the delay. But the LCD still the same as it was before @Justme \$\endgroup\$ – Kiroloes Amir Jun 12 at 17:00
  • \$\begingroup\$ I don't know how and why you added 0x20 command but unless you provide the new code I can't verify if it is correct or not, but simply adding a 0x20 command will not fix this sequence. \$\endgroup\$ – Justme Jun 12 at 17:26
  • \$\begingroup\$ the new code is on the top \$\endgroup\$ – Kiroloes Amir Jun 12 at 17:53
  • \$\begingroup\$ It's still wrong. You do realize that the CMD subroutine sends two nybbles, so if the display is in 8-bit mode after powerup, using CMD to send 30h as two nybbles will make the display receive two bytes 3Xh and 0Xh so display receives them as 3Fh and 0Fh (it has internal pull-ups on data pins). \$\endgroup\$ – Justme Jun 12 at 18:01
  • \$\begingroup\$ MOV R0, #30H ;8-BIT INITIALIZATION CLR RS ;COMMAND MODE SETB E ACALL DELAY_MS CLR E ACALL DELAY_MS MOV R1, #04H ; 4MS DELAY ACALL DELAY_MS is that right \$\endgroup\$ – Kiroloes Amir Jun 12 at 18:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.