LIST p=16F628 ;tell assembler what chip we are using
include "P16F628.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)
cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
templcd ;temp store for 4 bit mode
templcd2
temp01 ;use in identifying wire no.
pointer ;use to point the next address
endc
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
org 0x0000
goto Start
Main_Text addwf PCL, f
retlw 'I'
retlw 'N'
retlw 'I'
retlw 'T'
retlw 'I'
retlw 'A'
retlw 'L'
retlw 'I'
retlw 'S'
retlw 'I'
retlw 'N'
retlw 'G'
retlw 0x00
Text_Fail addwf PCL, f
retlw ' '
retlw 'F'
retlw 'A'
retlw 'I'
retlw 'L'
retlw 0x00
Text_Pass addwf PCL, f
retlw 'A'
retlw 'L'
retlw 'L'
retlw ' '
retlw 'P'
retlw 'A'
retlw 'S'
retlw 'S'
retlw 0x00
Text_space addwf PCL, f
retlw ' '
retlw 0x00
Start movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)
Initialise clrf count
clrf PORTA
clrf PORTB
clrf temp01
movlw 0x30
movwf pointer
SetPorts bsf STATUS, RP0 ;select bank 1
movlw 0x00 ;PORT A for LCD
movwf LCD_TRIS
movlw 0x80 ;PORT B for Decoder
movwf TRISB
bcf STATUS, RP0 ;select bank 0
call LCD_Init ;setup LCD
call LCD_Line1
clrf count ;set counter register to zero
Main movf count, w ;put counter value in W
call Main_Text ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto Sub_Main
call LCD_Char ;Display Initialising
nop
incf count, f
goto Main
Sub_Main movlw b'01000000'
movwf PORTB
Call Repeat
movlw b'01001000'
movwf PORTB
Call Repeat
movlw b'01010000'
movwf PORTB
Call Repeat
movlw b'01011000'
movwf PORTB
Call Repeat
movlw b'01100000'
movwf PORTB
Call Repeat
movlw b'01101000'
movwf PORTB
Call Repeat
movlw b'01110000'
movwf PORTB
Call Repeat
movlw b'01111000'
movwf PORTB
Call Repeat
movlw b'00000000'
movwf PORTB
Call Repeat
movlw b'00001000'
movwf PORTB
Call Repeat
movlw b'00010000'
movwf PORTB
Call Repeat
movlw b'00011000'
movwf PORTB
Call Repeat
movlw b'00100000'
movwf PORTB
Call Repeat
movlw b'00101000'
movwf PORTB
Call Repeat
movlw b'00110000'
movwf PORTB
Call Repeat
movlw b'00111000'
movwf PORTB
Call Repeat
Goto Display
Return
Repeat Call Check
bsf PORTB, 0
Call Check
bcf PORTB, 0
bsf PORTB, 1
Call Check
bsf PORTB, 0
Call Check
bcf PORTB, 0
bcf PORTB, 1
bsf PORTB, 2
Call Check
bsf PORTB, 0
Call Check
bcf PORTB, 0
bsf PORTB, 1
Call Check
bsf PORTB, 0
Call Check
Return
Check Incf temp01, f ;indicate which wire is testing
Call Delay255
Call Delay255
btfss PORTB, 7 ;check input for '1', skip if '1'
Call Fail_Test
Return
Fail_Test movfw pointer
movwf FSR
movfw temp01
movwf INDF
Incf pointer,f ;next address
Return
Display movfw pointer ;put value in W
xorlw 0x30 ;is it a zero?
btfsc STATUS, Z
Call Display_Pass ;pointer stay at 0x30 meaning nothing fail
Call Display_Fail ;if not, display which wire fail
Return
Display_Pass
Call LCD_Clr
Call LCD_Line1
clrf count ;set counter register to zero
All_pass movf count, w ;put counter value in W
call Text_Pass ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto Final_Delay
call LCD_Char ;Display All pass
nop
incf count, f
goto All_pass
Display_Fail
Call LCD_Clr
Call LCD_Line1 ;display on first line
Wire_Fail02 Decf pointer,f
movfw pointer
movwf FSR
movfw INDF
call LCD_CharD ;convert to ASCII
goto Fail_Check
Spacing movf count, w
Call Text_space ;Spacing
xorlw 0x00
btfsc STATUS, Z
goto Wire_Fail02
call LCD_Char ;display spacing
nop
incf count, f
goto Spacing
Fail_Check clrf count
movfw pointer
xorlw 0x30
btfsc STATUS, Z
goto Spacing
Fail_Print movf count, w
Call Text_Fail ;Fail
xorlw 0x00
btfsc STATUS, Z
goto Final_Delay
call LCD_Char ;display Fail
nop
incf count, f
goto Fail_Print
Final_Delay Call Delay255
Call Final_Delay
;Subroutines and text tables
;LCD routines
;Initialise LCD
LCD_Init call Delay100 ;wait for LCD to settle
movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x28 ;Set display shift
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd ;Set cursor off
call LCD_Clr ;clear display
retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_CharD addlw 0x30 ;add 0x30 to convert to ASCII
LCD_Char movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00
LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00
LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
retlw 0x00
LCD_Line2W addlw 0xc0 ;move to 2nd row, column W
call LCD_Cmd
retlw 0x00
LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00
Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00
;end of LCD routines
end