I'm trying to a write a basic "Hello World" to an 16x2 LCD on an easypic5. Using the MPLAB IDE, I've written the following program:
I've been scratching my head for a couple of hours, and have looked online for solutions, but everything I find is in the "C" programming language. I'm not able to initialize my LCD, and I don't know why.
Code:
;
; EasyPic5 version using PIC16F877
;Character based LCD driver routines for running the Hitachi HD44780
;in 4 bit mode. This program is configured to run on the
;EasyPIC5_Board at a clock rate of 8MHz.
;This program will print on both lines of the LCD and then stop.
;The program will write "Hello" on line 1.
;and it will write "World - " on line 2.
;-----------------------------------------------------------------
list p=16f887 ; list directive to define processor
#include <p16f887.inc> ; processor specific variable definitions
radix hex
errorlevel -302 ;Disable bank warning message in error list
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
__CONFIG _CONFIG1, _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOR_ON & _IESO_ON & _FCMEN_ON & _LVP_OFF & _DEBUG_OFF
__CONFIG _CONFIG2, _BOR40V & _WRT_OFF
;Note: All of the CONFIG designations must be contiguous on one line for each config register
;1 & 2.
;-------------------------------------------------------------------
cblock 0x20 ;start of general purpose registers
count ;used in looping routines
nib ;used for displaying single nibbles
currbyte ;current byte command or data being sent
lcount ;used inside ptimer routine
mcount ;used inside ptimer routine
ncount ;used inside ptimer routine
innerl ;used to send new values to ptimer routine
midl ;used to send new values to ptimer routine
outerl ;used to send new values to ptimer routine
cmdstatus ;used to indicate a command or data
endc
;-------------------------------------------------------------------
LCDPORT Equ PORTB
LCDTRIS Equ TRISB
RS Equ 0x04 ;LCD register select
E Equ 0x05 ;LCD enable line
RW ;not used on EasyPIC_Board
cmd_on Equ 0x00 ;bit 0 used as command / data flag
org 0x0000
clrf count
clrf PORTB
banksel TRISB ;Bank1
movlw 0x00 ;outputs
movwf LCDTRIS
banksel PORTB ;Bank0
call delay150 ;wait for LCD to settle
call LCDInit ;setup LCD
; movlw 0x09
call LCD_Line1
clrf count ;set counter register to zero
Message movf count, w ;put counter value in W
call Text ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto NextMessage
call LCD_Char
incf count, f
goto Message
NextMessage call LCD_Line2 ;move to 2nd row, first column
clrf count ;set counter register to zero
Message2 movf count, w ;put counter value in W
call Text2 ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto EndMessage
call LCD_Char
incf count, f
goto Message2
EndMessage
;End of commands test
Stop goto Stop ;endless loop
;Program stops executing here!
;==============================================================
;Testing commands here
movlw 0x09 ;address location 9 on line 1
call LCD_Line2W
movlw 0xaf ;Note only uses last hex digit
call HEX_1 ;write single digit
movlw 0x0d
call HEX_1 ;write another single digit
movlw 'A'
call HEX_DBL
movlw 0x06
call LCD_CharD
;Initialise LCD
LCDInit movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x18 ;Display Cursor Shift
call LCD_Cmd
movlw 0x28 ;Function Set
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
return
LCD_Cmd bsf cmdstatus,cmd_on ;set the command bit high
goto LCD_Char
LCD_CharD addlw 0x30 ;add 30 hex to decimal digits
LCD_Char movwf currbyte
swapf currbyte ;it is necessary to swap the
movfw currbyte ;nibble because the EasyPic5
;uses the lower four bits for
;data transfer instead of the
;upper four bits like the
;EasyPic4
call Snd_nibl ;send first nibble
movf currbyte,w ;get the other nibble
swapf currbyte,w ;get the other nibble
call Snd_nibl ;send the second nibble
bcf cmdstatus,cmd_on ;clear the command bit
call delay3
return
;Sends one nibble to controller / Used by commands and characters
;Will set Register select low for command if cmdstatus, bit 0 is high
;Will set Register select high for char data if cmdstatus, bit 0 is low
Snd_nibl andlw 0x0f ;clear lower nibble of W
movwf LCDPORT
btfss cmdstatus,cmd_on ;check if command or character
goto charnib
bcf LCDPORT,RS ;RS line to 0 for command
goto pulse
charnib bsf LCDPORT,RS ;RS line to 1 for character
pulse call Pulse_e ;Pulse the E line high
return
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
return
LCD_Line2 movlw 0xC0 ;move to 2nd row, first column
call LCD_Cmd
return
LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
return
LCD_Line2W addlw 0xC0 ;move to 2nd row, column W
call LCD_Cmd
return
LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
return
LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
return
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
return
HEX_1 movwf nib ;displays a nibble in a single hex char
goto singl
HEX_DBL movwf nib ;displays a byte in two hex chars
swapf nib,w
andlw 0x0f
call HEX_Table
call LCD_Char
singl movf nib,w
andlw 0x0f
call HEX_Table
call LCD_Char
return
Pulse_e bsf LCDPORT,E ;Pulse the Enable line
nop
bcf LCDPORT,E
return
;end of LCD routines
HEX_Table ADDWF PCL, f
DT "0123456789ABCDEF"
Text addwf PCL, f
DT "Hello", 0h
Text2 ADDWF PCL, f
DT "World - ", 0h
;-------------------------------------------
;routine to load 150msec delay into ptimer
;values based on 8MHz clock rate
delay150 movlw 0xFE
movwf innerl
movlw 0xC4
movwf midl
movlw 0x02
movwf outerl
call ptimer
return
;routine to load 3msec delay into ptimer
;values based on 8MHz clock rate
delay3 movlw 0xFF
movwf innerl
movlw 0x08
movwf midl
movlw 0x01
movwf outerl
call ptimer
return
;=====================================================================
;ptimer is a 3 loop counter. Adjust time delay by loading values into
;lcount, mcount, and ncount from the calling routine
;--------------OUTER LOOP---------------------------------------->>>
ptimer movf outerl,w ;loaded from calling routine
movwf lcount
;--------------MIDDLE LOOP--------------------------------->>
loadm movf midl,w ;loaded fro calling routine
movwf mcount
;-----------INNER MOST LOOP----------------------------->
loadn movf innerl,w ;loaded from calling routine
movwf ncount
decn decfsz ncount,f ;decrement N
goto decn ;again thru inner loop N
;-------------------------------------------------------<
decfsz mcount,f ;decrement M
goto loadn ;again thru middle loop M
;---------------------------------------------------------<<
decfsz lcount,f ;decrement L
goto loadm ;again thru outer loop L
;---------------------------------------------------------------<<<
return ;done
;=====================================================================
end
;-------------------------------------------------
I've been scratching my head for a couple of hours, and have looked online for solutions, but everything I find is in the "C" programming language. I'm not able to initialize my LCD, and I don't know why.