;*************************************
; Author : Mike Baird
; Program : 32 bit calculator
; Date : June 13th, 2010
;*************************************
List P=16F88
#include "P16F88.INC"
__CONFIG _CONFIG1, _PWRTE_OFF & _WDT_OFF & _INTRC_IO & _BODEN_OFF & _LVP_OFF & _CP_OFF & _MCLR_OFF
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
errorlevel -302,-305
;*** Cblock ***
CBLOCK 0x20
Count1 ; For delay!
CountA ;
CountB ;
CountC
TempLCD ; For LCD
; For all math
InputA3
InputA2 ; For storing input keys
InputA1
InputA0 ;
InputB3
InputB2
InputB1 ;
InputB0 ;
REGA3 ; 32-bit Accumulator a, lsb+3, ms-byte
REGA2 ; 32-bit Accumulator a, lsb+2
REGA1 ; 32-bit Accumulator a, lsb+1
REGA0 ; 32-bit Accumulator a, ls-byte
REGB3 ; 32-bit Accumulator b, lsb+3, ms-byte
REGB2 ; 32-bit Accumulator b, lsb+2
REGB1 ; 32-bit Accumulator b, lsb+1
REGB0 ; 32-bit Accumulator b, ls-byte
REGC3 ; Scracth for Remainder and Multiplication
REGC2
REGC1
REGC0
DSIGN
DIGIT1 ; 10^9, billions
DIGIT2 ; 10^8
DIGIT3 ; 10^7
DIGIT4 ; 10^6, millions
DIGIT5 ; 10^5
DIGIT6 ; 10^4
DIGIT7 ; 10^3, thousands
DIGIT8 ; 10^2
DIGIT9 ; 10^1
DIGIT10 ; 10^0
DCOUNT ; digit count
MCOUNT
MTEMP
Temp
Operation
ENDC
;*** Defines ***
; PORTB
#Define Column1 PORTB,3
#Define Column2 PORTB,2
#Define Column3 PORTB,1
#Define Column4 PORTB,0
#Define Row1 PORTB,7
#Define Row2 PORTB,6
#Define Row3 PORTB,5
#Define Row4 PORTB,4
LCD_Port EQU PORTA
RS EQU 0x04
RW EQU 0x06
E EQU 0x07
;*** START OF RAM ***
ORG 0x000 ; Start of program vector
GOTO Start ;
ORG 0x004 ; Interrupt vector
;*** Configuration ***
Start
clrf PORTA ; PortA all low
clrf PORTB ; PortB all low
bsf STATUS,RP0 ; Bank 1
movlw b'01100000' ; Make clock 4Mhz
iorwf OSCCON ;
movlw b'00100000' ; Bit 5 input
movwf TRISA
movlw 0xF0 ; PortA all output except MCLR
movwf TRISB ; PortB half in half out
clrf ANSEL ; Make PORTA all digital I/O
bcf STATUS,RP0 ; Bank 0
call Delay100 ; wait for LCD to settle
call LCD_Init ; Initialize LCD
;*** Main ***
bsf Column1 ; set up columns
bsf Column2
bsf Column3
bsf Column4
Main
movlw .32 ; 32 registers to clear
movwf CountC
movlw InputA3
movwf FSR
clrf INDF ; Clear all registers sequentially
incf FSR
decfsz CountC
goto $-3
; *** Input and Load ACa0-4 ***
call Delay255
call CheckKeys
movwf Temp
call LCD_Char
movlw .48 ; Turn into 0-9 (Not ASCII)
subwf Temp,W
movwf REGA0
movwf InputA0
InputACa
call Delay255
call CheckKeys
movwf Temp ; Hold temporarily
xorlw '*' ; was operation pressed?
btfsc STATUS,Z
goto ChooseOperation ; yes it was
movlw .10 ; multiply by 10
movwf REGB0 ; on every other pass it will now x10
call multiply ; e.g. for 1 digit * X
movf Temp,W ; Show key
call LCD_Char
movlw .48 ; Turn into 0-9 (Not ASCII)
subwf Temp,W
addwf REGA0,W
movwf REGA0
movwf InputA0
addcf REGA1
movf REGA1,W
movwf InputA1
movf REGA2,W
movwf InputA2
movf REGA3,W
movwf InputA3
goto InputACa
;*** Input and Load ACb0-4 ***
ChooseOperation:
call LCD_Line2
call Delay255
call CheckKeys
movwf Temp
xorlw '*'
bz RedrawFirst
movf Temp,w
movwf Operation
movlw .48
subwf Operation,w
call OperationTable
call LCD_Char
goto ChooseOperation
OperationTable
addwf PCL
nop
retlw '+'
retlw '-'
retlw '*'
retlw '/'
retlw 's'
RedrawFirst
call LCD_Clr
call LCD_Line1
movf InputA0,w
movwf REGA0
movf InputA1,w
movwf REGA1
movf InputA2,w
movwf REGA2
movf InputA3,w
movwf REGA3
call bin2dec
movlw .10
movwf CountC
movlw DIGIT1
movwf FSR
clearzeros
movf INDF,W ; Clear all leading 0's
bnz answerdisplay
incf FSR
decf CountC
movf CountC,W ; If answer is actually 0, display just one Zero
xorlw .1
btfsc STATUS,Z
goto answerdisplay
goto clearzeros
answerdisplay:
movf INDF,W
call LCD_CharD
incf FSR ; point at next digit
decfsz CountC
goto answerdisplay
movlw .48
subwf Operation,w
call OperationTable
call LCD_Char
NextInput
call Delay255
call CheckKeys
movwf Temp
call LCD_Char
movlw .48 ; Turn into 0-9 (Not ASCII)
subwf Temp,W
movwf REGA0
movwf InputB0
clrf REGA1
InputACb
call Delay255
call CheckKeys
movwf Temp ; Hold temporarily
xorlw '*' ; was multiply again pressed?
btfsc STATUS,Z
goto MathTime ; yes it was, we are done getting inputs
movlw .10 ; multiply by 10
movwf REGB0 ; on every other pass it will now x10
call multiply
movf Temp,W ; Show key
call LCD_Char
movlw .48
subwf Temp,W
addwf REGA0,W
movwf REGA0
movwf InputB0
addcf REGA1
movf REGA1,W
movwf InputB1
movf REGA2,W
movwf InputB2
movf REGA3,W
movwf InputB3
goto InputACb
;*** Perform Operation ***
MathTime
movf InputA0,W
movwf REGA0
movf InputA1,W
movwf REGA1
movf InputA2,W
movwf REGA2
movf InputA3,W
movwf REGA3
movf InputB0,W
movwf REGB0
movf InputB1,W
movwf REGB1
movf InputB2,W
movwf REGB2
movf InputB3,W
movwf REGB3
movlw .48
subwf Operation
clrc
rlf Operation,w
addwf PCL
nop
nop
call add
goto DisplayResult
call subtract
goto DisplayResult
call multiply
goto DisplayResult
call divide
goto DisplayResult
call sqrt
;*** Display Result ***
DisplayResult
call bin2dec
call LCD_Line2 ; Display answer on Line 2
movlw '='
call LCD_Char
movlw ' '
call LCD_Char
movlw .1
xorwf DSIGN
skpz
goto $+3
movlw '-'
call LCD_Char
movlw .10
movwf CountC
movlw DIGIT1
movwf FSR
ClearZeros
movf INDF,W ; Clear all leading 0's
bnz AnswerDisplay
incf FSR
decf CountC
movf CountC,W ; If answer is actually 0, display just one Zero
xorlw .1
btfsc STATUS,Z
goto AnswerDisplay
goto ClearZeros
AnswerDisplay:
movf INDF,W
call LCD_CharD
incf FSR ; point at next digit
decfsz CountC
goto AnswerDisplay
call Delay255
call CheckKeys ; A key press will now restart the calculator
call LCD_Clr
call LCD_Line1
call Delay255 ; Debouncing
goto Main
;********************************** Math Subroutines **************************************
;{
;*** 32 BIT SIGNED SUTRACT ***
;REGA - REGB -> REGA
;Return carry set if overflow
subtract
call negateb ;Negate REGB
skpnc
return ;Overflow
;*** 32 BIT SIGNED ADD ***
;REGA + REGB -> REGA
;Return carry set if overflow
add
movf REGA3,w ;Compare signs
xorwf REGB3,w
movwf MTEMP
call addba ;Add REGB to REGA
clrc ;Check signs
movf REGB3,w ;If signs are same
xorwf REGA3,w ;so must result sign
btfss MTEMP,7 ;else overflow
addlw 0x80
return
;*** 32 BIT SIGNED MULTIPLY ***
;REGA * REGB -> REGA
;Return carry set if overflow
multiply
clrf MTEMP ;Reset sign flag
call absa ;Make REGA positive
skpc
call absb ;Make REGB positive
skpnc
return ;Overflow
call movac ;Move REGA to REGC
call clra ;Clear product
movlw D'31' ;Loop counter
movwf MCOUNT
muloop
call slac ;Shift left product and multiplicand
rlf REGC3,w ;Test MSB of multiplicand
skpnc ;If multiplicand bit is a 1 then
call addba ;add multiplier to product
skpc ;Check for overflow
rlf REGA3,w
skpnc
return
decfsz MCOUNT,f ;Next
goto muloop
btfsc MTEMP,0 ;Check result sign
call negatea ;Negative
return
;*** 32 BIT SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero
divide
clrf MTEMP ;Reset sign flag
movf REGB0,w ;Trap division by zero
iorwf REGB1,w
iorwf REGB2,w
iorwf REGB3,w
sublw 0
skpc
call absa ;Make dividend (REGA) positive
skpc
call absb ;Make divisor (REGB) positive
skpnc
return ;Overflow
clrf REGC0 ;Clear remainder
clrf REGC1
clrf REGC2
clrf REGC3
call slac ;Purge sign bit
movlw D'31' ;Loop counter
movwf MCOUNT
dvloop
call slac ;Shift dividend (REGA) msb into remainder (REGC)
movf REGB3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf REGC3,w
skpz
goto dtstgt
movf REGB2,w
subwf REGC2,w
skpz
goto dtstgt
movf REGB1,w
subwf REGC1,w
skpz
goto dtstgt
movf REGB0,w
subwf REGC0,w
dtstgt
skpc ;Carry set if remainder >= divisor
goto dremlt
movf REGB0,w ;Subtract divisor (REGB) from remainder (REGC)
subwf REGC0,f
movf REGB1,w
skpc
incfsz REGB1,w
subwf REGC1,f
movf REGB2,w
skpc
incfsz REGB2,w
subwf REGC2,f
movf REGB3,w
skpc
incfsz REGB3,w
subwf REGC3,f
clrc
bsf REGA0,0 ;Set quotient bit
dremlt
decfsz MCOUNT,f ;Next
goto dvloop
btfsc MTEMP,0 ;Check result sign
call negatea ;Negative
return
;*** ROUND RESULT OF DIVISION TO NEAREST INTEGER ***
round
clrf MTEMP ;Reset sign flag
call absa ;Make positive
clrc
call slc ;Multiply remainder by 2
movf REGB3,w ;Test if remainder (REGC) >= divisor (REGB)
subwf REGC3,w
skpz
goto rtstgt
movf REGB2,w
subwf REGC2,w
skpz
goto dtstgt
movf REGB1,w
subwf REGC1,w
skpz
goto rtstgt
movf REGB0,w
subwf REGC0,w
rtstgt
skpc ;Carry set if remainder >= divisor
goto rremlt
incfsz REGA0,f ;Add 1 to quotient
goto rremlt
incfsz REGA1,f
goto rremlt
incfsz REGA2,f
goto rremlt
incf REGA3,f
skpnz
return ;Overflow,return carry set
rremlt
btfsc MTEMP,0 ;Restore sign
call negatea
return
;*** 32 BIT SQUARE ROOT ***
;sqrt(REGA) -> REGA
;Return carry set if negative
sqrt
rlf REGA3,w ;Trap negative values
skpnc
return
call movac ;Move REGA to REGC
call clrba ;Clear remainder (REGB) and root (REGA)
movlw D'16' ;Loop counter
movwf MCOUNT
sqloop
rlf REGC0,f ;Shift two msb's
rlf REGC1,f ;into remainder
rlf REGC2,f
rlf REGC3,f
rlf REGB0,f
rlf REGB1,f
rlf REGB2,f
rlf REGC0,f
rlf REGC1,f
rlf REGC2,f
rlf REGC3,f
rlf REGB0,f
rlf REGB1,f
rlf REGB2,f
setc ;Add 1 to root
rlf REGA0,f ;Align root
rlf REGA1,f
rlf REGA2,f
movf REGA2,w ;Test if remdr (REGB) >= root (REGA)
subwf REGB2,w
skpz
goto ststgt
movf REGA1,w
subwf REGB1,w
skpz
goto ststgt
movf REGA0,w
subwf REGB0,w
ststgt
skpc ;Carry set if remdr >= root
goto sremlt
movf REGA0,w ;Subtract root (REGA) from remdr (REGB)
subwf REGB0,f
movf REGA1,w
skpc
incfsz REGA1,w
subwf REGB1,f
movf REGA2,w
skpc
incfsz REGA2,w
subwf REGB2,f
bsf REGA0,1 ;Set current root bit
sremlt
bcf REGA0,0 ;Clear test bit
decfsz MCOUNT,f ;Next
goto sqloop
clrc
rrf REGA2,f ;Adjust root alignment
rrf REGA1,f
rrf REGA0,f
return
;*** 32 BIT SIGNED BINARY TO DECIMAL ***
;REGA -> DIGITS 1 (MSD) TO 10 (LSD) & DSIGN
;DSIGN = 0 if REGA is positive, 1 if negative
;Return carry set if overflow
;Uses FSR register
bin2dec
clrf MTEMP ;Reset sign flag
call absa ;Make REGA positive
skpnc
return ;Overflow
call clrdig ;Clear all digits
movlw D'32' ;Loop counter
movwf MCOUNT
b2dloop
rlf REGA0,f ;Shift msb into carry
rlf REGA1,f
rlf REGA2,f
rlf REGA3,f
movlw DIGIT10
movwf FSR ;Pointer to digits
movlw D'10' ;10 digits to do
movwf DCOUNT
adjlp
rlf INDF,f ;Shift digit and carry 1 bit left
movlw D'10'
subwf INDF,w ;Check and adjust for decimal overflow
skpnc
movwf INDF
decf FSR,f ;Next digit
decfsz DCOUNT,f
goto adjlp
decfsz MCOUNT,f ;Next bit
goto b2dloop
btfsc MTEMP,0 ;Check sign
bsf DSIGN,0 ;Negative
clrc
return
;*** 32 BIT SIGNED DECIMAL TO BINARY ***
;Decimal DIGIT1 thro DIGIT(X) & DSIGN -> REGA
;Set DSIGN = 0 for positive, DSIGN = 1 for negative values
;Most significant digit in DIGIT1
;Enter this routine with digit count in w register
;Return carry set if overflow
;Uses FSR register
dec2bin
movwf MTEMP ;Save digit count
movlw D'32' ;Outer bit loop counter
movwf MCOUNT
d2blp1
movlw DIGIT1-1 ;Set up pointer to MSD
movwf FSR
movf MTEMP,w ;Inner digit loop counter
movwf DCOUNT
movlw D'10'
clrc ;Bring in '0' bit into MSD
d2blp2
incf FSR,f
skpnc
addwf INDF,f ;Add 10 if '1' bit from prev digit
rrf INDF,f ;Shift out LSB of digit
decfsz DCOUNT,f ;Next L.S. Digit
goto d2blp2
rrf REGA3,f ;Shift in carry from digits
rrf REGA2,f
rrf REGA1,f
rrf REGA0,f
decfsz MCOUNT,f ;Next bit
goto d2blp1
movf INDF,w ;Check for overflow
addlw 0xFF
skpc
rlf REGA3,w
skpnc
return
btfsc DSIGN,0 ;Check result sign
call negatea ;Negative
return
;UTILITY ROUTINES
;Add REGB to REGA (Unsigned)
;Used by add, multiply,
addba
movf REGB0,w ;Add lo byte
addwf REGA0,f
movf REGB1,w ;Add mid-lo byte
skpnc ;No carry_in, so just add
incfsz REGB1,w ;Add carry_in to REGB
addwf REGA1,f ;Add and propagate carry_out
movf REGB2,w ;Add mid-hi byte
skpnc
incfsz REGB2,w
addwf REGA2,f
movf REGB3,w ;Add hi byte
skpnc
incfsz REGB3,w
addwf REGA3,f
return
;Move REGA to REGC
;Used by multiply, sqrt
movac
movf REGA0,w
movwf REGC0
movf REGA1,w
movwf REGC1
movf REGA2,w
movwf REGC2
movf REGA3,w
movwf REGC3
return
;Clear REGB and REGA
;Used by sqrt
clrba
clrf REGB0
clrf REGB1
clrf REGB2
clrf REGB3
;Clear REGA
;Used by multiply, sqrt
clra
clrf REGA0
clrf REGA1
clrf REGA2
clrf REGA3
return
;Check sign of REGA and convert negative to positive
;Used by multiply, divide, bin2dec, round
absa
rlf REGA3,w
skpc
return ;Positive
;Negate REGA
;Used by absa, multiply, divide, bin2dec, dec2bin, round
negatea
movf REGA3,w ;Save sign in w
andlw 0x80
comf REGA0,f ;2's complement
comf REGA1,f
comf REGA2,f
comf REGA3,f
incfsz REGA0,f
goto nega1
incfsz REGA1,f
goto nega1
incfsz REGA2,f
goto nega1
incf REGA3,f
nega1
incf MTEMP,f ;flip sign flag
addwf REGA3,w ;Return carry set if -2147483648
return
;Check sign of REGB and convert negative to positive
;Used by multiply, divide
absb
rlf REGB3,w
skpc
return ;Positive
;Negate REGB
;Used by absb, subtract, multiply, divide
negateb
movf REGB3,w ;Save sign in w
andlw 0x80
comf REGB0,f ;2's complement
comf REGB1,f
comf REGB2,f
comf REGB3,f
incfsz REGB0,f
goto negb1
incfsz REGB1,f
goto negb1
incfsz REGB2,f
goto negb1
incf REGB3,f
negb1
incf MTEMP,f ;flip sign flag
addwf REGB3,w ;Return carry set if -2147483648
return
;Shift left REGA and REGC
;Used by multiply, divide, round
slac
rlf REGA0,f
rlf REGA1,f
rlf REGA2,f
rlf REGA3,f
slc rlf REGC0,f
rlf REGC1,f
rlf REGC2,f
rlf REGC3,f
return
;Set all digits to 0
;Used by bin2dec
clrdig
clrf DSIGN
clrf DIGIT1
clrf DIGIT2
clrf DIGIT3
clrf DIGIT4
clrf DIGIT5
clrf DIGIT6
clrf DIGIT7
clrf DIGIT8
clrf DIGIT9
clrf DIGIT10
return
;}
;*** Keypad Subroutine ***
;{
CheckKeys
bsf Column1
bcf Column4
btfss Row1 ; Yes, check rows
retlw 'A' ; if row is off, store 2 in work reg
btfss Row2 ; Check which row was pressed and fill Temp with appropriate value
retlw 'B' ;
btfss Row3 ;
retlw 'C' ;
btfss Row4 ;
retlw 'D' ;
COLUMN3
bsf Column4
bcf Column3
btfss Row1 ; Yes, check rows
retlw '3' ; if row is off, store 2 in work reg
btfss Row2 ; Check which row was pressed and fill Temp with appropriate value
retlw '6'
btfss Row3 ;
retlw '9' ;
btfss Row4 ;
retlw '#' ;
COLUMN2
bsf Column3
bcf Column2
btfss Row1 ;
retlw '2' ;
btfss Row2 ;
retlw '5' ;
btfss Row3 ;
retlw '8' ;
btfss Row4 ;
retlw '0' ;
COLUMN1
bsf Column2
bcf Column1
btfss Row1 ;
retlw '1'
btfss Row2 ;
retlw '4' ;
btfss Row3 ;
retlw '7' ;
btfss Row4 ;
retlw '*'
goto CheckKeys
;}
;*** LCD routines ***
;{
LCD_Init
movlw 0x20 ; Set to 4 bit mode
call LCD_Cmd ;
movlw 0x28 ; Set display shift to 1
call LCD_Cmd ;
movlw 0x06 ; Set display move right after character sent
call LCD_Cmd ;
movlw 0x0D ; Set display on, don't underline cursor but flash it
call LCD_Cmd ;
call LCD_Clr ; Clear display
call LCD_CurOff
return
LCD_Cmd
movwf TempLCD
swapf TempLCD,W ; Send upper nibble
andlw 0x0F ; Clear upper 4 bits of W (Not to interfere with RS,RW and E)
movwf LCD_Port
bcf LCD_Port,RS ; RS line to 0
bsf LCD_Port,E ; Pulse the E line high
nop
bcf LCD_Port,E
movf TempLCD,W ; Send lower nibble
andlw 0x0F ; Clear upper 4 bits of W
movwf LCD_Port
bcf LCD_Port,RS ; RS line to 0
bsf LCD_Port,E ; Pulse the E line high
nop
bcf LCD_Port,E
call Delay5
return
LCD_CharD
addlw 0x30 ; Convert W 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,RS ; RS line to 1
bsf LCD_Port,E ; Pulse the E line high
nop
bcf LCD_Port,E
movf TempLCD,W ; Send lower nibble
andlw 0x0F ; Clear upper 4 bits of W
movwf LCD_Port
bsf LCD_Port,RS ; RS line to 1
bsf LCD_Port,E ; Pulse the E line high
nop
bcf LCD_Port,E
call Delay5
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
;}
;*** Delay Routines ***
;{
Delay255
movlw d'255' ; 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 d'5' ; 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
return
;}
;*** End ***
END
list p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _RC_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;***** VARIABLE DEFINITIONS
w_temp EQU 0x7D ; variable used for context saving
status_temp EQU 0x7E ; variable used for context saving
pclath_temp EQU 0x7F ; variable used for context saving
cblock 0x20
count ;used in loops
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
templcd ;temp store for 4 bit mode
endc
;**********************************************************************
ORG 0x000 ; processor reset vector
nop ; nop required for icd
goto Start ; go to beginning of program
ORG 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf pclath_temp ; save off contents of PCLATH register
; isr code can go here or be located as a call subroutine elsewhere
movf pclath_temp,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
;Subroutines:
Init
clrw ; Zero.
movwf PORTB ;resets input/output ports
bsf STATUS,RP0 ; Select Bank 1
movlw b'00000000' ; Set port B bits 0-3 as outputs b0-b3 connected to lcd d4-d7 pins
;and b5-b7 connected to RS,RW,E
movwf TRISB ; Set TRISB register
bcf STATUS,RP0 ; Select Bank 0
call Delay100 ;wait for LCD to settle
retlw 0
LCD_Init
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 0x0d ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
retlw 0x00
LCD_Cmd
movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf PORTB
bcf PORTB,6 ;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 PORTB
bcf PORTB,6 ;RS line to 0
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Char
movwf templcd
swapf templcd,w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf PORTB
bsf PORTB,6 ;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 PORTB
bsf PORTB,6 ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
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
Text
addwf PCL, f
retlw 'H'
retlw 'e'
retlw 'l'
retlw 'l'
retlw 'o'
retlw 0x00
Pulse_e
bsf PORTB,7
nop
bcf PORTB,7
retlw 0x00
EndMessage
Stop goto Stop ;endless loop
;Program Start:
Start
call Init
Main
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 EndMessage
call LCD_Char
incf count, f
goto message
END
I have included contrast control (you can look at the circuit on the attachment) and adjusted it, but still the is no dispaly on the LCD, I would be glad if you can paste the circuit diagram of PIC Tutorial Three - LCD ModulesAs you don't have a contrast control it may well be working, but you can't see it - add a contrast control - as a minimum it will let you adjust it until it displays a single row of squares, this shows the LCD is functioning, but not been initialised
I have connected the crystal oscillator as shown in the circuit diagram on the attachment and I have also changed the configuration bitsNot sure if it matters for the SIM but you dont have an oscillator connected?
I have included contrast control (you can look at the circuit on the attachment) and adjusted it, but still the is no dispaly on the LCD, I would be glad if you can paste the circuit diagram of PIC Tutorial Three - LCD Modules
(Tutorial 3.1 ) I think it would be helpful since it will make me realise my problem, because I copied some of the routines from Tutorial 3.1.
I constructed the circuit similar to that of PIC Tutorial - LCD BoardAll the circuits are on the tutorial site, under Hardware.
I constructed the circuit similar to that of PIC Tutorial - LCD BoardAll the circuits are on the tutorial site, under Hardware.
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
If you can measure V, A and ohms, why would you need a calculator?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?