Parece que tiene "problemas" en su código.
Los comentarios se refieren a PORTD, pero su código utiliza PORTB.
La sincronización con los módulos HD44780 más antiguos puede ser complicada.
Puede encontrar útil esta implementación completa y probada:
;
; 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
Esto utiliza los datos de 4 bits y la interfaz de control de 3 bits para el módulo LCD.
Este código no utiliza los datos de 8 bits, por lo que tendrá que modificar la máscara para LCD_DATA_BITS para la posición correcta de los bits nybble.