📄 d.txt
字号:
addtens10
movlw 1
addtensx0
movwf mantissa
movlw 0
addtensxx
movwf exponent ;exponent
;flows into addtens
;addtens: enter with mantissa and exponent registers loaded.
;value specified gets added into decimal registers.
;w/flags/mantissa/exponent affected. Returns xlsb->xmsb updated.
addtens
movf mantissa,w ;check mantissa value
btfsc status,z
return ;return if nothing to do!
bcf status,c ;clear carry
rrf exponent,w ;divide exponent by two (nibble oriented)
addlw xlsb ;point to proper nibble set
movwf fsr ;use it for indirect addressing of nibble sets
addlw -(xmsb+1) ;don't go too far!
btfsc status,z
return ;return if all available digits done
btfsc exponent,0 ;lsb tells us even or odd exponent
goto oddstuff
evenstuff
call even ;handle rightmost nibble
incf exponent,f ;prepare for next higher digit
goto addtens ;see if more to do...
oddstuff
call odd ;handle leftmost nibble
incf exponent,f ;prepare for next higher digit
goto addtens ;see if more to do...
even
movlw b'00001111' ;just look at right nibble
andwf indf,w ; of value pointed to
addwf mantissa,f ;add mantissa+current value
; and save in mantissa
movf mantissa,w ;copy into w, too
addlw -d'10' ;same as x-10
btfsc status,z
goto setevenzero ;10-10=0
btfsc status,c
goto setevenpositive ;cy=1 if x-10 is positive
setevennegative
movlw b'11110000'
andwf indf,f ;clear out right nibble
movf mantissa,w ;copy mantissa+current value into w
; (value is less than 10)
iorwf indf,f ;now byte contains new right nibble
clrf mantissa ;clear carryout pointer
return ;all done! no carryout.
setevenzero
movlw b'11110000'
andwf indf,f ;clear out right nibble
clrf mantissa ;set mantissa to 1 for carryout.
incf mantissa,f ; 0+1=1
return ;now update next because of carryout
setevenpositive
movwf mantissa ;save positive value
movlw b'11110000'
andwf indf,f ;clear out right nibble
movf mantissa,w ;copy mantissa+current value into w
; (value is less than 10)
iorwf indf,f ;now byte contains new right nibble
clrf mantissa ;set mantissa to 1 for carryout.
incf mantissa,f ; 0+1=1
return ;now update next because of carryout
odd
swapf indf,f ;swap nibbles
call even ; and use even routines! how sneaky.
swapf indf,f ;swap nibbles back to normal
return ;return with possible carry in mantissa
;sample calling routine
; call lcdclear1
; movlw onetext-starttext ;note how we subtract starttext address
; call textout ; to make an 8 bit address PIC can handle.
; call lcdclear2 ; sometext routine and attendant data
; movlw twotext-starttext ; should be within 1st 256 bytes of program
; call textout ; to ensure addressability.
textout
movwf temp1 ;save that address!
textloop
call sometext ;retlw a byte
addlw 0 ;set z flag if we recovered terminating 0
btfsc status,z
return ;once we got 0 we are done
call lcdout ;everything else we send to lcd
incf temp1,f ;NEXT!
movf temp1,w ;need new address in both temp1 and w
goto textloop ;do a whole string of 'em
;routine to output packed bcd+ nibbles
dataout
call lcdhome1 ;data goes on 1st line of lcd
movlw 8 ;8 bytes = 16 packed bcd+ nibbles
movwf temp2 ;temp2 holds byte count
movlw xmsb
movwf fsr ;indirect addressing set to xmsb
dataloop
swapf indf,w ;get left nibble, since we are outputting
; digits etc from left to right (msb->lsb)
call convert ;convert 4 bits into full regular ascii
call lcdout ;and display it on lcd (including commas, etc.)
movf indf,w ;then right nibble
call convert
call lcdout
decf fsr,f ;point to next
decf temp2,f
btfsc status,z
return ;done when all 8 bytes done
goto dataloop ;otherwise keep going.
;these routines are used to "shift and drop" coded items such as commas and decimal
;points into the packed bcd+ decimal set.
;first we have some space-saving attempts that code some of the more popular sd constructs
sd4c
movlw d'4'
sdxc
movwf shift
movlw ncomma
goto sd
sd12s
movlw d'12'
movwf shift
movlw nspace
goto sd
sd12p
movlw d'12'
sdxp
movwf shift
movlw nperiod
goto sd
sd15x
movlw d'15'
movwf shift
movlw nx
;flows into shiftanddrop
;enter with shift position in (shift)temp1 and replacement data in w.
;use fsr method. shift left
;the method used for shifting is to shift a nibble at a time
shiftanddrop
sd ;(I use the shorter label when I have to type.)
movwf wlcdtemp ;steal the lcd's temp register to conserve resources.
movlw xmsb
movwf fsr ;fsr now points to msb
movf temp1,w ;check for 'more to do'
btfsc status,z ;if position is 0 no shift to do
goto stuffleft ; so just stuff data
nextleft
swapf indf,f ;otherwise 'shift' nibble left
movf indf,w
andlw b'11110000' ;clear right nibble
movwf indf ;of current byte
decf temp1,f ;update shift counter
btfsc status,z
goto stuffright ;if done, stuff new data
;otherwise do nextright...
nextright
decf fsr,f ;if not done, shift across bytes
swapf indf,w ; copy high nibble into low nibble and to w
andlw b'00001111' ;get nibble to be shifted...
incf fsr,f ;access 'current' location again
iorwf indf,f ;replace with shifted data.
decf fsr,f ;point to next byte!
decf temp1,f ;update shift counter
btfsc status,z
goto stuffleft ;if done, stuff new data
goto nextleft
stuffleft
movf indf,w ;recover current byte
andlw b'00001111' ;clear left nibble
movwf indf ;replace byte
swapf wlcdtemp,w ;move replacement nibble into position
andlw b'11110000' ;just replace left nibble
iorwf indf,f ;done!
return
stuffright
movf indf,w ;recover current byte
andlw b'11110000' ;clear right nibble
movwf indf ;replace byte
movf wlcdtemp,w
andlw b'00001111' ;just replace right nibble
iorwf indf,f ;done!
return
;a whole bunch of lcd routines to make life easier
initwlcd
call wmillisecs ;wait w ms (may be power up condition)
movlw b'00110000'
andlw b'11110000' ;just high bits first
movwf nibbles ;save high nibbles
movf shadowb,w ;get control bits from flags
andlw b'00001111' ; they are in lower 4 bits
iorwf nibbles,w ;save result in w
movwf portb ;output high bits and controls...
bsf portb,lcde ;begin enable strobe...
nop ;add extra 1 us delay
bcf portb,lcde ;end enable strobe
return
lcdreset
movlw d'16'
call initwlcd ;wait 16 ms (may be power up condition)
;do lcd song and dance init thing
movlw d'1'
call initwlcd ;wait 1 ms (may be power up condition)
;do lcd song and dance init thing
;most data sheets show 3 initializations,
;but I have always found 2 to be enough.
movlw d'1'
call wmillisecs ;wait 1 ms (we don't read busy flag)
movlw b'00100000'
andlw b'11110000' ;just high bits first
movwf nibbles ;save high nibbles
movf shadowb,w ;get control bits from flags
andlw b'00001111' ; they are in lower 4 bits
iorwf nibbles,w ;save result in w
movwf portb ;set for 4 bit mode
bsf portb,lcde ;begin enable strobe...
nop ;add extra 1 us delay for good luck
bcf portb,lcde ;end enable strobe
movlw d'1'
call wmillisecs ;wait 1 ms to allow it to take
;from here on out we use 4 bit interface!
;proper delays are built-in.
movlw b'00101000' ;set 4 bit, 2 lines, 5x7 font
call lcdcommand
movlw b'00001100' ;display on, cursor off,blink off
call lcdcommand
call lcdclear ;clear lcd
movlw b'00000110' ;increment cursor and no display shift
call lcdcommand
return
;lcd commands: called subroutines. each clobbers w.
lcdclear
movlw b'00000001'
goto lcdcommand
lcdclear1 call lcdhome1
call lcdlineclear
goto lcdhome1
lcdclear2 call lcdhome2
call lcdlineclear
goto lcdhome2
lcdhome1
movlw b'00000010' ;home to line 1 and set display to normal
goto lcdcommand
lcdaddress
iorlw b'10000000' ;append command to address in w.
goto lcdcommand ; sets ddram address.
lcdhome2 movlw b'11000000' ;set ddram address to h'40'
goto lcdcommand ; which is line 2
lcdlineclear movlw d'16' ;lines are 16 characters long
movwf temp1
llcloop movlw ' ' ;clear by writing 16 spaces
call lcdout
decf temp1,f ;update loop count and w
movf temp1,f
btfss status,z
goto llcloop
return
;lcdout: called subroutine. w contains data to be sent in two 4 bit nibbles.
;includes delay since we do not read the busy flag. w unaffected.
lcdout
bsf shadowb,lcdrs ;set data mode in flags register
call lcdnibbles ;do common lcd routine
return
;lcdcommand: called subroutine. w contains data to be sent in two 4 bit nibbles.
;includes delay since we do not read the busy flag. w not affected.
lcdcommand
bcf shadowb,lcdrs ;set instruction mode in flags register
call lcdnibbles ;do common lcd routine
movlw d'4'
call wmillisecs ;wait another 4 ms (we don't read busy flag)
movf wlcdtemp,w ;we have w back!
return
;NOTE! lcdnibbles is the low-level interface between data to be displayed and
; the actual hardware implementation of the 4 data bits and control stuff.
; if you implement a different port useage, then this routine would have to
; be modified. pay special attention to the necessary bit masks and port used!
lcdnibbles
movwf wlcdtemp ;save w!
movlw d'1'
call _200usecs ;wait min. .2 ms (we don't read busy flag)
bcf shadowb,lcde ;set e strobe low (default)
movf wlcdtemp,w ;recover original
andlw b'11110000' ;just high bits first
movwf nibbles ;save high nibbles
movf shadowb,w ;get control bits from flags
andlw b'00001111' ; they are in lower 4 bits
iorwf nibbles,w ;save result in w
movwf portb ;output high bits and controls...
bsf portb,lcde ;begin enable strobe...
nop ;add extra 1 us delay
bcf portb,lcde ;end enable strobe
swapf wlcdtemp,f ;swap hi and lo nibbles of original
;(leave lcdrs bit set as-is)
movf wlcdtemp,w ;recover swapped nibble
andlw b'11110000' ;now low bits are in high bits
movwf nibbles ;save this nibble (which was low bits)
movf shadowb,w ;get control bits from flags
andlw b'00001111' ; they are in lower 4 bits
iorwf nibbles,w ;save result in w
movwf portb ;output low bits...
bsf portb,lcde ;begin enable strobe...
nop ;slight delay
bcf portb,lcde ;strobe e goes low now
bsf shadowb,lcdrs ;default in flags is data mode
bcf shadowb,lcde ;default in flags is strobe enable low
swapf wlcdtemp,f ;back to normal...
movf wlcdtemp,w ;we have w back!
return
;==============================================================================
; _200usecs: (subroutine) : 200 usec delay.
;==============================================================================
_200usecs
movlw (d'200'-3)/3 ;number of loops
movwf xmillisec ;(shared register)
_200loop
decf xmillisec,f ;count down
btfss status,z
goto _200loop
return
delay1000
call xmillisecs
delay800
call xmillisecs
delay600
call xmillisecs
delay400
call xmillisecs
;flow into xmillisecs for last 200 ms delay
;==============================================================================
; xmillisecs: (subroutine) : 200 msec delay. flows into wmillisec.
;==============================================================================
xmillisecs
movlw d'200' ;delay...
;==============================================================================
; wmillisecs: (subroutine) : delay for w millisecs. tuned for 4.00 mhz xtal.
;==============================================================================
;called subroutine set to generate delays.
;enter with # of milliseconds to delay in W
wmillisecs
movwf xmillisec ;save # of millisecs in w to delay.
incf xmillisec,f ;adjust to account for initial decrement.
;first (outer) loop.
wmloop1
decfsz xmillisec,f ;update first (outer) loop
goto wmloopa ;if more to do, do it.
return ;done when xmillisec=0.
wmloopa
clrf ymillisec ;second (inner) loop
;256 loops (256+1 becomes 0)
wmloopb
decfsz ymillisec,f ;update 256 part of inner loop.
goto wmloopb ;3 usec per loop
movlw d'75'+1
movwf ymillisec ;75 loops for third loop
wmloopc
decfsz ym
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -