It would appear that you have "issues" in your code.
The comments refer to PORTD but your code used PORTB.
Timing with the older HD44780 modules can be tricky.
You may find this complete and tested implementation useful:
;
; Filename: main.asm
; Author: dan1138
; Target: PIC18F452
; Assembler: MPASMWIN v5.22
; Assembler mode: Absolute
;
; Files required: p18f452.inc
;
; Description:
;
; Initialize an HD44780 based LCD module with a PIC18F452 using an external 10MHz crystal
;
; Notes:
; Tested using the DM163022-1 PICDEM2 Plus demo board.
; I know it's obsolete and impossible to find but I got one so I used it.
;
list P=18F452, r=dec, n=0, c=255
#include "p18f452.inc"
config OSC = HS ; Oscillator Selection bits (HS oscillator)
config OSCS = OFF ; Oscillator System Clock Switch Enable bit (Oscillator system clock switch option is disabled (main oscillator is source))
config PWRT = OFF ; Power-up Timer Enable bit (PWRT disabled)
config BOR = OFF ; Brown-out Reset Enable bit (Brown-out Reset disabled)
config BORV = 27 ; Brown-out Reset Voltage bits (VBOR set to 2.7V)
config WDT = OFF ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
config WDTPS = 128 ; Watchdog Timer Postscale Select bits (1:128)
config CCP2MUX = ON ; CCP2 Mux bit (CCP2 input/output is multiplexed with RC1)
config STVR = ON ; Stack Full/Underflow Reset Enable bit (Stack Full/Underflow will cause RESET)
config LVP = OFF ; Low Voltage ICSP Enable bit (Low Voltage ICSP disabled)
config CP0 = OFF ; Code Protection bit (Block 0 (000200-001FFFh) not code protected)
config CP1 = OFF ; Code Protection bit (Block 1 (002000-003FFFh) not code protected)
config CP2 = OFF ; Code Protection bit (Block 2 (004000-005FFFh) not code protected)
config CP3 = OFF ; Code Protection bit (Block 3 (006000-007FFFh) not code protected)
config CPB = OFF ; Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code protected)
config CPD = OFF ; Data EEPROM Code Protection bit (Data EEPROM not code protected)
config WRT0 = OFF ; Write Protection bit (Block 0 (000200-001FFFh) not write protected)
config WRT1 = OFF ; Write Protection bit (Block 1 (002000-003FFFh) not write protected)
config WRT2 = OFF ; Write Protection bit (Block 2 (004000-005FFFh) not write protected)
config WRT3 = OFF ; Write Protection bit (Block 3 (006000-007FFFh) not write protected)
config WRTC = OFF ; Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write protected)
config WRTB = OFF ; Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write protected)
config WRTD = OFF ; Data EEPROM Write Protection bit (Data EEPROM not write protected)
config EBTR0 = OFF ; Table Read Protection bit (Block 0 (000200-001FFFh) not protected from Table Reads executed in other blocks)
config EBTR1 = OFF ; Table Read Protection bit (Block 1 (002000-003FFFh) not protected from Table Reads executed in other blocks)
config EBTR2 = OFF ; Table Read Protection bit (Block 2 (004000-005FFFh) not protected from Table Reads executed in other blocks)
config EBTR3 = OFF ; Table Read Protection bit (Block 3 (006000-007FFFh) not protected from Table Reads executed in other blocks)
config EBTRB = OFF ; Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from Table Reads executed in other blocks)
;
; /* Specify the System clock frequency in Hz */
#define FOSC 10000000
; /* Specify the Peripheral clock frequency in Hz */
#define FCYC (FOSC/4)
;
; Define the LCD port pins
#define E_PIN_OUT LATD,6
#define RW_PIN_OUT LATD,5
#define RS_PIN_OUT LATD,4
#define E_PIN_DIR TRISD,6
#define RW_PIN_DIR TRISD,5
#define RS_PIN_DIR TRISD,4
#define LCD_DATA_BITS 0x0F
#define LCD_PORT_IN PORTD
#define LCD_PORT_OUT LATD
#define LCD_PORT_DIR TRISD
#define LCD_FORMAT (FOUR_BIT&LINES_5X7)
#define USE_FAST_CLOCK
; Start address of each line
#define LINE_ONE 0x00
#define LINE_TWO 0x40
#define LINE_THREE 0x14
#define LINE_FOUR 0x54
;
; Power On Reset entry point
org 0
goto start
;
; Interrupt Service Routine entry point
org 0x08
ISR_vevtor:
retfie 1
;
; Main application start
start:
movlw 0x07
movwf ADCON1 ; Make all pins digital I/O
bcf TRISD,7
bsf LATD,7 ; Turn on power to the DM163022-1 PICDEM2 Plus LCD module
call LCD_Init ; Initial the HD44780 module
movlw HIGH(SignOn)
movwf LCD_pszRomStr+1
movlw LOW(SignOn) ; Point to sign on message in ROM memory
movlw LINE_ONE
call LCD_SetDDRamAddr ; Position to first line
movwf LCD_pszRomStr ; Display sign on message
call LCD_Putrs
;
; Main application loop
main:
goto main
SignOn:
DT "PIC18F452",0
;
;
;/* Display ON/OFF Control defines */
#define DON b'00001111' ;/* Display on */
#define DOFF b'00001011' ;/* Display off */
#define CURSOR_ON b'00001111' ;/* Cursor on */
#define CURSOR_OFF b'00001101' ;/* Cursor off */
#define BLINK_ON b'00001111' ;/* Cursor Blink */
#define BLINK_OFF b'00001110' ;/* Cursor No Blink */
;/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT b'00010011' ;/* Cursor shifts to the left */
#define SHIFT_CUR_RIGHT b'00010111' ;/* Cursor shifts to the right */
#define SHIFT_DISP_LEFT b'00011011' ;/* Display shifts to the left */
#define SHIFT_DISP_RIGHT b'00011111' ;/* Display shifts to the right */
;/* Function Set defines */
#define FOUR_BIT b'00101111' ;/* 4-bit Interface */
#define EIGHT_BIT b'00111111' ;/* 8-bit Interface */
#define LINE_5X7 b'00110011' ;/* 5x7 characters, single line */
#define LINE_5X10 b'00110111' ;/* 5x10 characters */
#define LINES_5X7 b'00111011' ;/* 5x7 characters, multiple line */
;
; This code assumes an oscillator of 40MHz
;
; The the fastest oscillator a PIC18F452 can use is 40MHz.
;
; When USE_FAST_CLOCK is defined the delays are adjusted
; for a 40MHz oscillator.
;
#ifdef USE_FAST_CLOCK
#define DELAY_FOR_FAST_CLOCK call Delay2us
#else
#define DELAY_FOR_FAST_CLOCK
#endif
;
; This RAM is used by the LCD interface routines.
;
; Warning:
; This must be RAM in the access RAM memory space
;
cblock 0x70
LCD_byte:1 ; byte sent to or read from LCD
LCD_BusyBit:1 ; Mask of where the BUSY bit is located
LCD_pszRomStr:2 ; pointer to ASCIIZ string in ROM
endc
; Delay2us() provide at least 2 microseconds of delay at 40MHz
Delay2us:
bra _n2
; LCD_Delay() provide at least 5 milliseconds of delay
LCD_Delay:
;
; If we are using a fast clock make
; the delays work for a 40MHz clock.
;
#ifdef USE_FAST_CLOCK
call LCD_D7
LCD_D7:
call LCD_D8
call LCD_D8
call LCD_D8
call LCD_D8
#endif
LCD_D8:
bra _n0
_n0:bra _n1
_n1:movlw d'249'
LCD_D9:
call _n2
addlw -1
bnz LCD_D9
_n2:bra _n3
_n3:bra _n4
_n4:bra _n5
_n5:bra _n6
_n6:bra _n7
_n7:bra _n8
_n8:bra _n9
_n9:return
; LCD_DelayPOR() provides at least 15ms delay
LCD_DelayPOR:
call LCD_Delay
call LCD_Delay
bra LCD_Delay
;
;**********************************************************************
; Function: LCD_Busy
; Description:
; This routine reads the busy status of the
; Hitachi HD44780 LCD controller.
;
; Inputs: none
;
; Outputs: none
;
; Returns: WREG = Not zero when status of LCD controller is busy
;
; Notes:
; The busy bit is not reported in the same nibble
; on all HD44780 "compatible" controllers.
; If you have a Novatek 7605 type controller some
; versions report these nibbles in reverse order.
;
; This code has been tested with a Novatek 7605
; and the real Hitachi HD44780.
;
LCD_Busy:
movf LCD_BusyBit,F ; Check if busy bit avaliable.
bz LCD_DelayPOR ; Use a 15ms delay when busy not available.
bcf RS_PIN_OUT
bsf RW_PIN_OUT
bcf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
btfsc LCD_BusyBit,7
movf LCD_PORT_IN,W ; The standard LCD returns the BUSY flag first
bcf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
btfsc LCD_BusyBit,3
movf LCD_PORT_IN,W ; A Non standard LCD returns the BUSY flag second
bcf E_PIN_OUT
andlw (LCD_DATA_BITS&(~LCD_DATA_BITS>>1))
bnz LCD_Busy
return
;
; Send a byte to LCD using 4-bit mode
LCD_PutByte:
movlw ~LCD_DATA_BITS
andwf LCD_PORT_DIR,F ; Make LCD port bits outputs
andwf LCD_PORT_OUT,F ; Make LCD port bits zero
bcf RW_PIN_OUT
;
; send first 4-bits
swapf LCD_byte,W
andlw LCD_DATA_BITS
iorwf LCD_PORT_OUT,F
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bcf E_PIN_OUT
;
; send second 4-bits
xorwf LCD_byte,W
andlw LCD_DATA_BITS
xorwf LCD_PORT_OUT,F
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bcf E_PIN_OUT
; set data bits for input
movlw LCD_DATA_BITS
iorwf LCD_PORT_DIR,F
movf LCD_byte,W
return
;
; Read a byte to LCD using 4-bit mode
LCD_GetByte:
bsf RW_PIN_OUT
;
; read first 4-bits
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
movf LCD_PORT_IN,W
bcf E_PIN_OUT
andlw LCD_DATA_BITS
movwf LCD_byte
;
; read second 4-bits
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
movf LCD_PORT_IN,W
bcf E_PIN_OUT
andlw LCD_DATA_BITS
swapf LCD_byte,F
iorwf LCD_byte,F
movf LCD_byte,W
return
;
;**********************************************************************
; Function Name: LCD_SetCGRamAddr
; Description:
; This routine sets the character generator
; address of the Hitachi HD44780 LCD
; controller.
;
; Inputs: W = character generator ram address
;
; Outputs: none
;
; Returns: nothing
;
LCD_SetCGRamAddr:
iorlw 0x40 ; Write cmd and address to port
movwf LCD_byte ; save byte going to LCD
call LCD_Busy
bcf RS_PIN_OUT
bra LCD_PutByte
;
;**********************************************************************
; Function: LCD_SetDDRamAddr
; Description:
; This routine sets the display data address
; of the Hitachi HD44780 LCD controller.
;
; Inputs: W = display data address
;
; Outputs: none
;
; Returns: nothing
;
LCD_SetDDRamAddr:
iorlw 0x80 ; Write cmd and address to port
movwf LCD_byte ; save byte going to LCD
call LCD_Busy
bcf RS_PIN_OUT
bra LCD_PutByte
;
;**********************************************************************
; Function Name: LCD_WriteCmd
; Description:
; This routine writes a command to the Hitachi
; HD44780 LCD controller.
;
; Inputs: W = command to send to LCD
;
; Outputs: none
;
; Returns: nothing
;
LCD_WriteCmd:
movwf LCD_byte ; save byte going to LCD
call LCD_Busy
bcf RS_PIN_OUT
bra LCD_PutByte
;
;**********************************************************************
; Function: LCD_WriteData
; Description:
; This routine writes a data byte to the
; Hitachi HD44780 LCD controller. The data
; is written to the character generator RAM or
; the display data RAM depending on what the
; previous SetxxRamAddr routine was called.
;
; Inputs: W = data to send to LCD
;
; Outputs: none
;
; Returns: nothing
;
LCD_WriteData:
movwf LCD_byte ; save byte going to LCD
call LCD_Busy
bsf RS_PIN_OUT
call LCD_PutByte
bcf RS_PIN_OUT
return
;
;**********************************************************************
; Function: LCD_Init
; Description:
; This routine configures the LCD. Based on
; the Hitachi HD44780 LCD controller. The
; routine will configure the I/O pins of the
; microcontroller, setup the LCD for 4-bit
; mode and clear the display.
;
; Inputs: none
;
; Outputs: none
;
; Returns: nothing
;
LCD_Init:
clrf LCD_BusyBit
movlw ~LCD_DATA_BITS
andwf LCD_PORT_DIR,F ; Make LCD data bus an output
bcf E_PIN_DIR ; Make LCD data enable strobe an output
bcf RW_PIN_DIR ; Make LCD Read/Write select an output
bcf RS_PIN_DIR ; Make LCD Register select an output
andwf LCD_PORT_OUT,F ; Drive all LCD pins low
bcf E_PIN_OUT
bcf RW_PIN_OUT
bcf RS_PIN_OUT
call LCD_DelayPOR ; Wait for LCD to complete power on reset
movlw b'00110011' ; force LCD into 8-bit mode
iorwf LCD_PORT_OUT,F
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bcf E_PIN_OUT
call LCD_Delay ; Required 5ms delay
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bcf E_PIN_OUT
call LCD_Delay ; minimum 100us delay but use 5ms
movlw b'00100010' ; set LCD into 4-bit mode
xorwf LCD_PORT_OUT,W
andlw LCD_DATA_BITS
xorwf LCD_PORT_OUT,F
bsf E_PIN_OUT
DELAY_FOR_FAST_CLOCK
bcf E_PIN_OUT
call LCD_Delay
movlw LCD_DATA_BITS ; Make LCD data pins inputs
iorwf LCD_PORT_DIR,F
movlw LCD_FORMAT
andlw 0x0F ; Allow only 4-bit mode for
iorlw 0x20 ; HD44780 LCD controller.
call LCD_WriteCmd
;
; Find position of busy bit
; Required when using 4-bit mode.
;
movlw LINE_ONE+1
call LCD_SetDDRamAddr
call LCD_Busy
call LCD_GetByte
xorlw 0x01
btfsc STATUS,Z ; skpnz
bsf LCD_BusyBit,7
xorlw 0x11
btfsc STATUS,Z ; skpnz
bsf LCD_BusyBit,3
;
; Turn display off
;
movlw (DOFF & CURSOR_OFF & BLINK_OFF)
call LCD_WriteCmd
;
; Turn display on
;
movlw (DON & CURSOR_OFF & BLINK_OFF)
call LCD_WriteCmd
;
; Clear display
;
movlw (0x01) ; Clear display
call LCD_WriteCmd
;
; Set cursor shift direction
;
movlw (SHIFT_CUR_LEFT)
call LCD_WriteCmd
;
; Initialize CGRAM
;
movlw 0
call LCD_SetCGRamAddr
movlw LOW(CGRAM_Table)
movwf LCD_pszRomStr
movlw HIGH(CGRAM_Table)
movwf LCD_pszRomStr+1
call LCD_Putrs
;
; Put cursor on line one, left most position
;
movlw LINE_ONE
call LCD_SetDDRamAddr
return
;
;**********************************************************************
; Function: LCD_Putrs
; Description:
; This routine writes a string of bytes to the
; Hitachi HD44780 LCD controller. The data
; is written to the character generator RAM or
; the display data RAM depending on what the
; previous SetxxRamAddr routine was called.
;
; Inputs: LCD_pszRomStr: pointer to string
;
; Outputs: none
;
; Returns: nothing
;
LCD_Putrs:
call TableLookUp
iorlw 0
btfsc STATUS,Z ; skpnz
return
call LCD_WriteData
movlw Next_instruction-$
Next_instruction:
addwf LCD_pszRomStr,F
btfsc STATUS,C ; skpnc
incf LCD_pszRomStr+1,F
bra LCD_Putrs
TableLookUp:
clrf PCLATU
movf LCD_pszRomStr+1,W
movwf PCLATH
movf LCD_pszRomStr,W
movwf PCL
;
; This table is used to write
; default characters to the
; Character Generator RAM of
; the LCD module.
;
CGRAM_Table:
dt B'10001000' ; CGRAM character 1
dt B'10000100'
dt B'10001110'
dt B'10000100'
dt B'10001000'
dt B'10000000'
dt B'10000000'
dt B'10011111'
dt B'10001110' ; CGRAM character 2
dt B'10010001'
dt B'10010000'
dt B'10010000'
dt B'10010001'
dt B'10001110'
dt B'10000000'
dt B'10011111'
dt B'10001110' ; CGRAM character 3
dt B'10010001'
dt B'10010000'
dt B'10010011'
dt B'10010001'
dt B'10001110'
dt B'10000000'
dt B'10011111'
dt B'10000000' ; CGRAM character 4
dt B'10001110'
dt B'10001010'
dt B'10001010'
dt B'10001110'
dt B'10000000'
dt B'10000000'
dt B'10011111'
dt B'10011110' ; CGRAM character 5
dt B'10010001'
dt B'10010001'
dt B'10011110'
dt B'10010010'
dt B'10010001'
dt B'10000000'
dt B'10011111'
dt B'10001110' ; CGRAM character 6
dt B'10010001'
dt B'10010001'
dt B'10011111'
dt B'10010001'
dt B'10010001'
dt B'10000000'
dt B'10011111'
dt B'10010001' ; CGRAM character 7
dt B'10011011'
dt B'10010101'
dt B'10010101'
dt B'10010001'
dt B'10010001'
dt B'10000000'
dt B'10011111'
dt B'10000100' ; CGRAM character 8
dt B'10001000'
dt B'10011100'
dt B'10001000'
dt B'10000100'
dt B'10000000'
dt B'10000000'
dt B'10011111'
dt B'00000000' ; End of table marker
end
This uses the 4-bit data and 3-bit control interface for the LCD module.
This code does not use the 8-bit data so you will need to modify the mask for LCD_DATA_BITS for the correct position of the nybble bits.