Hello everyone. I have been studying and practicing on the 18f1320 and have gotten LEDs to blink and do different things. However, I am trying to implement a LCD screen and am having problems and based on what I have read everywhere on the internet I think it is with the initialization or with the setting of my internal oscillator but haven't been able to resolve it regardless of what I try. It turns on but shows black squares all the way across the top. I have the 44780 LCD set up as 8 bit with D0-D7 as B0-B7 and E-A2, RW-A1, RS-A0. I know it may be alot to ask but I would be really thankful if someone would take a look at the code I put together and maybe see if they see something. I am using MPLAB ASM and have no errors or warnings but still can't get it to work. Thanks.
Rich (BB code):
#include<p18f1320.inc>
__config _CONFIG1H, _INTIO2_OSC_1H
__config _CONFIG2L, _PWRT_ON_2L
__config _CONFIG2H, _WDT_OFF_2H
__config _CONFIG3H, _MCLRE_OFF_3H
__config _CONFIG4L, _LVP_OFF_4L
;set ports
LCD_DATA EQU PORTB ; LCD data lines interface
LCD_DATA_TRIS EQU TRISB
LCD_CTRL EQU PORTA ; LCD control lines interface
;misc
LCD_TEMP EQU 0x020 ; LCD subroutines internal use
TABLE_INDEX EQU 0x021 ; Index to table strings
COUNT EQU 0x022 ; A counter
DELAY EQU 0x023 ; Used in DELAYxxx routines
X_DELAY EQU 0x024 ; Used in X_DELAYxxx routines
;PORTA Bits
LCD_E EQU 2 ; LCD Enable control line
LCD_RW EQU 1 ; LCD Read/Write control line
LCD_RS EQU 0 ; LCD Register-Select control line
;PORTB Bits
DB7 EQU 7 ; LCD dataline 7 (MSB)
DB6 EQU 6 ; LCD dataline 6
DB5 EQU 5 ; LCD dataline 5
DB4 EQU 4 ; LCD dataline 4
DB3 EQU 3 ; LCD dataline 3
DB2 EQU 2 ; LCD dataline 2
DB1 EQU 1 ; LCD dataline 1
DB0 EQU 0 ; LCD dataline 0 (LSB)
;Screen Lines
LCD_LINE0 EQU 0x000
LCD_LINE1 EQU 0x040
org 0
GOTO START
START:
movlw b'01110000' ; setup INTOSC for 8-MHz |B1
movwf OSCCON ; or b'01110000'
movlw B'01111111' ; Set all analog ports to digital only (both porta & portb)
movwf ADCON1
movlw b'11111111' ; Set PORTA direction all input
movwf TRISA
movlw b'00000000' ; Set PORTB direction all output
movwf TRISB
CLRF INTCON ; Clear int-flags, Disable interrupts
CLRF PCLATH ; Keep in lower 2KByte
CLRF PORTA ; ALL PORT output should output Low.
CLRF PORTB
cALL LCDINIT ; Initialize LCDisplay
MOVLW 0x030 ; ASCII '0'
MOVWF COUNT
MOVLW LCD_LINE0
CALL LCDSDDA ; Position cursor leftmost on first line
CALL TABLE_MSG ; Display message
MOVLW LCD_LINE0 + 0x013
CALL LCDSDDA ; Position cursor
MOVF COUNT, W
CALL LCDPUTCHAR ; Display line number
INCF COUNT, F
MOVLW LCD_LINE1
CALL LCDSDDA
CALL TABLE_MSG
MOVLW LCD_LINE1 + 0x013
CALL LCDSDDA
MOVF COUNT, W
CALL LCDPUTCHAR
LOOP
GOTO LOOP ; Stay here forever
TABLE_MSG
MOVLW 0 ; Startindex of table message
DISP_MSG
MOVWF TABLE_INDEX ; Holds message address
CALL MSG1
ANDLW 0x0FF ; Check if at end of message
BTFSC STATUS, Z ; (zero returned at end)
GOTO TABLE_MSG_END
CALL LCDPUTCHAR ; Display character
MOVF TABLE_INDEX, W ; Point to next character
ADDLW 1
GOTO DISP_MSG
TABLE_MSG_END RETURN
LCDINIT
; Busy-flag is not yet valid
CLRF LCD_CTRL ; ALL PORT output should output Low.
; power-up delay
MOVLW 0x01E
CALL X_DELAY500 ; 30 * 0.5mS = 15mS
; Busy Flag should be valid from here
MOVLW 0x038 ; 8-bit-interface, 2-lines
CALL LCDPUTCMD
MOVLW 0x000 ; disp.off, curs.off, no-blink
CALL LCDDMODE
CALL LCDCLEAR
MOVLW 0x004 ; disp.on, curs.off
CALL LCDDMODE
MOVLW 0x002 ; auto-inc (shift-cursor)
CALL LCDEMODE
RETURN
LCD_ENABLE
BSF LCD_CTRL, LCD_E ; LCD E-line High
NOP
BCF LCD_CTRL, LCD_E ; LCD E-line Low
NOP
BSF LCD_CTRL, LCD_E ; LCD E-line High
NOP
BCF LCD_CTRL, LCD_E ; LCD E-line Low
RETURN
LCDBUSY
MOVLW 0x0FF ; Set PORTB for input
MOVWF LCD_DATA_TRIS
BCF LCD_CTRL, LCD_RS; Set LCD for command mode
BSF LCD_CTRL, LCD_RW; Setup to read busy flag
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_DATA, W ; Read busy flag + DDram address
BCF LCD_CTRL, LCD_E ; LCD E-line Low
ANDLW 0x80 ; Check Busy flag, High = Busy
BTFSS STATUS, Z
GOTO LCDBUSY
LCDNOTBUSY BCF LCD_CTRL, LCD_RW
MOVLW 0x000
MOVWF LCD_DATA_TRIS ; Set PORTB for output
RETURN
LCDCLEAR
MOVLW 0x001
CALL LCDPUTCMD
RETURN
LCDHOME
MOVLW 0x002
CALL LCDPUTCMD
RETURN
LCDEMODE
ANDLW 0x003 ; Strip upper bits
IORLW 0x004 ; Function set
CALL LCDPUTCMD
RETURN
LCDDMODE
ANDLW 0x007 ; Strip upper bits
IORLW 0x008 ; Function set
CALL LCDPUTCMD
RETURN
LCDSCGA
ANDLW 0x03F ; Strip upper bits
IORLW 0x040 ; Function set
CALL LCDPUTCMD
RETURN
LCDSDDA
IORLW 0x080 ; Function set
CALL LCDPUTCMD
RETURN
LCDGADDR
MOVLW 0x0FF ; Set PORTB for input
MOVWF LCD_DATA_TRIS
BCF LCD_CTRL, LCD_RS; Set LCD for command mode
BSF LCD_CTRL, LCD_RW; Setup to read busy flag
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_DATA, W ; Read busy flag + RAM address
BCF LCD_CTRL, LCD_E ; LCD E-line Low
ANDLW 0x07F ; Strip upper bit
BCF LCD_CTRL, LCD_RW
MOVLW 0x000
MOVWF LCD_DATA_TRIS ; Set PORTB for output
RETURN
LCDPUTCHAR
MOVWF LCD_TEMP ; Character to be sent is in W
CALL LCDBUSY ; Wait for LCD to be ready
BCF LCD_CTRL, LCD_RW; Set LCD in read mode
BSF LCD_CTRL, LCD_RS; Set LCD in data mode
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_TEMP, W
MOVWF LCD_DATA ; Send data to LCD
BCF LCD_CTRL, LCD_E ; LCD E-line Low
RETURN
LCDPUTCMD
MOVWF LCD_TEMP ; Command to be sent is in W
CALL LCDBUSY ; Wait for LCD to be ready
BCF LCD_CTRL, LCD_RW; Set LCD in read mode
BCF LCD_CTRL, LCD_RS; Set LCD in command mode
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_TEMP, W
MOVWF LCD_DATA ; Send data to LCD
BCF LCD_CTRL, LCD_E ; LCD E-line Low
RETURN
DELAY500
MOVLW D'165' ; +1 1 cycle
MOVWF DELAY ; +2 1 cycle
DELAY500_LOOP DECFSZ DELAY, F ; step 1 1 cycle
GOTO DELAY500_LOOP ; step 2 2 cycles
DELAY500_END RETURN ; +3 2 cycles
X_DELAY500
MOVWF X_DELAY ; +1 1 cycle
X_DELAY500_LOOP
CALL DELAY500 ; step1 wait 500uSec
DECFSZ X_DELAY, F ; step2 1 cycle
GOTO X_DELAY500_LOOP ; step3 2 cycles
X_DELAY500_END RETURN ; +2 2 cycles
MSG1
addwf PCL ,F ;Jump to char pointed to in W reg
retlw 'T'
retlw 'E'
retlw 'S'
retlw 'T'
retlw ' '
retlw 'L'
retlw 'I'
retlw 'N'
retlw 'E'
retlw ' '
retlw 'N'
retlw 'U'
retlw 'M'
retlw ' '
retlw '#'
retlw ' '
MSG1_END
END ; End of program