📄 d.txt
字号:
bin24_2
offsetx ;pointer to current offset group
offset_0 ;zero adjust and comparison register
offset_1 ; for +/- comparisons.
offset_2
offset1_0 ;zero adjust for lowest scale
offset1_1
offset1_2
offset2_0 ;zero adjust for second scale
offset2_1
offset2_2
offset3_0 ;zero adjust for third scale
offset3_1
offset3_2
offset4_0 ;zero adjust for highest scale
offset4_1
offset4_2
over_0 ;overflow binary counter
over_1 ; tells us when sync wait is too long
over_2
endc
;aliases: these allow alternate name for systems resources.
; it makes reading the program a bit easier while conserving resources
xlsb = x10
xmsb = xfe
shift = temp1
drop = wlcdtemp
mantissa = temp0
exponent = temp3
;shadowb: bit assignments
;LOW 4 BITS ARE SHADOW FOR PORTB (Some have already been defined)
;periodin = h'00' ;inb selected period input
; (not used, but still registered)
;pselect = h'01' ;outb period select
; 0=period 1=px100
;lcde = h'02' ;outb lcd enable line
;lcdrs = h'03' ;outb lcd rs line (data/!instruction)
;flags: bit assignments
intoverflow = h'0' ;1=overflow during interrupt routine
; = h'1' ;not used
; = h'2' ;not used
gotit = h'3' ;1=we have data
plusminus = h'4' ;1=plus [bin24 > offset]
flipflop = h'5' ;flipflop indicator
; = h'6' ;not used
; = h'7' ;not used
;autoflags: bit assignments
manual = h'0' ;1=manual 0=auto
stop = h'1' ;1=stop 0=continue operation
rangechange = h'2' ;1=range change
toolong = h'3' ;1=too long
;conversions used by decimal nibble output routines
n0 = h'0'
n1 = h'1'
n2 = h'2'
n3 = h'3'
n4 = h'4'
n5 = h'5'
n6 = h'6'
n7 = h'7'
n8 = h'8'
n9 = h'9'
nspace = h'a' ;after number is produced
nplus = h'b' ; we add in special characters
nminus = h'c'
ncomma = h'd'
nperiod = h'e'
nx = h'f'
;
;program 1kx14 eeprom. (h'400') can only be changed via programmer, not on-the-fly.
;
org h'0000' ;set code origin
start goto setup ;we have to get past interrupt vector at 0004
;
;interrupts
; there is a single interrupt location at 004
; we must use flags to determine which interrupt...
; this info is in intcon
;
;intcon register: byte assignments
;
;enables... 1=enable 0=disable
;<7>=gie=global_int_enable
;<6>=eeie=eeprom_int_enable
;<5>=t0ie=t0_int_enable (enables <2> t0if)
;<4>=inte=int_enable (rb0/int) (enables <1> intf)
;<3>=rbie=rb_int_enable (enables <0> rbif)
;
;flags. software reset. 0=reset 1=flagged
;<2>=t0if=t0_int_flag
;<1>=intf=int_flag (rb0/int)
;<0>=rbif=rb_int_flag (rb7-rb4)
;
;upon power up and !mclr!, intcon will contain 0000 000x
;this means that initially all interrupts are disabled.
;
;note: option_reg register is used to program use of tmr0 and wdt
;
org h'0004' ;interrupt vector location
inthandler
;global interrupts automatically disabled on entry!
;we must save context using a somewhat convoluted scheme
movwf savew ;save w register!
swapf status,w ;save status! (twisted)
movwf savestatus ;(we use swapf so as not to disturb Z!)
movf fsr,w ;save fsr!
movwf savefsr
;actual interrupt code
movf tmr0,w ;save tmr0 in case we need it
movwf bin24_0 ;save it as low byte
btfss intcon,t0if ;if not t0if it should be intf
goto intperiod
inttmr0
bcf intcon,t0if ;reset t0if
incf bin24_1,f ;update 24 bit binary count
btfss status,z ;need carry?
goto intreturn ;all done.
incf bin24_2,f ;handled carry.
btfss status,z ;overflow?
goto intreturn ;if not, almost done
call set4 ;otherwise range to top
bsf flags,intoverflow ;set overflow indicator
;now flow into intperiod to terminate
; and turn off interrupts
;intperiod occurs when rbo/int triggers on edge (intf)
; (it is also entered when there is an overflow!)
intperiod
bsf flags,gotit ;tell regular program we have data!
clrf intcon ;turn off all interrupts
;& clear all interrupt flags
intreturn
comf porta,w ;copy inverted porta to w
andlw b'00011100' ;check three bits at once
btfsc status,z
goto intfinish ;if all are low, then none pushed
movf porta,w
movwf acopy ;save copy of porta for later use
;sort out the details later...
intfinish
movf savefsr,w ;restore fsr!
movwf fsr
swapf savestatus,w ;untwist twisted saved status
movwf status ;restore normalized status!
swapf savew,f ;restore w! first twist nibbles
swapf savew,w ;then twist again and place result in w.
;(how convoluted!)
retfie ;return from interrupt!
;gie is auto-re-enabled.
;note that jump tables and decoder tables are limited to 256 bytes of program space,
;and care must be taken that tables not cross over page boundaries.
;the limitation is based on the 8 bit addressing scheme employed in tables due to
;the size of w.
;decoder tables take the form:
;label
; addwf pcl,f ;this executes an effective jump forward
; retlw 'a' ;0 decodes as 'a'
; retlw 'b' ;1 decodes as 'b'
; retlw 'c' ;2 decodes as 'c' ... and so on
;
;
;convert special packed bcd+ nibbles into one of 16 8 bit code things
convert
andlw b'00001111' ;just the right nibble, please
addwf pcl,f ;this executes an effective jump forward 0-15
retlw '0'
retlw '1'
retlw '2'
retlw '3'
retlw '4'
retlw '5'
retlw '6'
retlw '7'
retlw '8'
retlw '9'
retlw ' ' ;decode the special stuff, too
retlw '+'
retlw '-'
retlw ','
retlw '.'
retlw '_' ;underscore _ used for non-existent digits
;text for lcd messages
sometext ;routine to extract string pieces
addwf pcl,f ;this executes an effective jump forward
starttext
begin1text dt "PIC CAP METER",0 ;put *your* name or message here 16 max
begin2text dt "Fr Tom McGahee",0 ;put *your* name or message here 16 max
autotext dt "AUTORANGING ",0
overtext dt "OVER-RANGE!",0
manual2text dt "MANUAL MODE",0
fourspaces dt " "
ufnfpftext dt " ",mu,"f nf pf",0 ;that mu is code for greek letter
zerotext dt "ZERO ALL RANGES",0
commontext = overtext ;share text to conserve memory
;(every little "bit" counts!)
;if you need extra bytes you can
;reduce the size of the messages,
;or even eliminate some entirely.
;but leave fourspaces and ufnfpftext alone,
;or at least modify them with care!
; pic16c84 pinouts
;
; ra2 <1> <18> ra1
; ra3 <2> <17> ra0
; (oc) ra4/tmr0<3> <16> osc1/clkin
; !mclr! <4> <15> osc2/clkout
; gnd <5> <14> +2 to +6 volts
; rb0/int <6> <13> rb7
; rb1 <7> <12> rb6
; rb2 <8> <11> rb5
; rb3 <9> <10> rb4
;
;osc1 & osc2 allow many types of timing choices. use device command to select.
;
;!mclr! tied high via resistor. use a switch to force it low for a reset.
;
;ra4 becomes the tmr0 external input if option_reg<5>=1. then option_reg<4> selects edge.
;ra4 is not ttl. it is oc out and schmitt in. use pullup resistor if needed.
;
;ra3-ra0 are ttl level.
;
;rb7-rb0 are ttl. weak pullups can be programmed for inputs if option_reg<7>=0
;rb0/int acts as int pin if intcon<4> inte=1. intcon<1> intf is flag. software reset.
;rb7-rb4 will generate an interrupt if intcon<3> rbie=1. intcon<0> rbif is flag. software reset.
;
setup ;initialize ports and registers
;ra4/tmr0<3>, ra3<2>, ra2<1>, ra1<18>, ra0<17>
;rb7<13>, rb6<12>, rb5<11>, rb4<10>
;rb3<9>, rb2<8>, rb1<7>, rb0/int<6>
;page 1 stuff includes option_reg, trisa, trisb, eecon1, eecon2
bsf status,rp0 ;allow access to page 1 stuff!
;*************** ignore mplab message[302]
movlw b'00011100' ;set porta direction for i/o pins
movwf trisa ;0=output 1=input
movlw b'00000001' ;set portb direction for i/o pins
;using rb0 as interrupt pin.
movwf trisb ;0=output 1=input
bcf option_reg,not_rbpu ;!rbpu! rb_pullup 0=enabled 1=disabled
; enabling is based on individual port-latch values
; we have disabled rb_pullup
bcf option_reg,intedg ;intedg 0=inc on falling 1=inc on rising
; <<note: intedg and t0se use opposite definition!>>
;we are incrementing on falling edge
; because initial sync is on falling edge
; and we want full period
;
;the edge used is later changed to speed
;up sync process.
bcf option_reg,t0cs ;t0cs timer0clocksource 0=internal clkout 1=ra4/int
; (rts in some data sheets)
; we clear so we can use internal clkout
bcf option_reg,t0se ;t0se timer0signaledge 0=inc on rising 1=inc on falling
; (rte in some data sheets)
; <<note: intedg and t0se use opposite definition!>>
; in our application edge makes no difference,
; so we arbitrarily choose rising edge.
bsf option_reg,psa ;psa prescalerassignment 0=tmr0 1=wdt
;we do not use wdt, but we set prescaler
;to wdt to allow div by 1 for tmr0!
;ps2-ps0 determine prescalerrate, which is
;dependent also on whether tmr0 or wdt is selected:
;wdt from 0-7 is div by 1 2 4 8 16 32 64 128
;tmr0 from 0-7 is div by 2 4 8 16 32 64 128 256
;if wdt is assigned prescaler, then tmr0 is div by 1
; here we will set prescaler to divide by 1 for tmr0
; by assigning the prescaler to the wdt
bcf option_reg,ps2 ;ps2 set for division by 1
bcf option_reg,ps1 ;ps1
bcf option_reg,ps0 ;ps0
;***************
bcf status,rp0 ;allow access to page 0 stuff again. (back to normal)
;now use movlw/movwf and/or clrf statements to initialize any desired variables
clrf flags ;reset all flag bits
clrf autoflags
movlw b'11111111' ;ensure initial 1's to allow auto-zero!
movwf acopy
;ready now to begin main user program.
mainprog
call lcdreset ;reset lcd, set for 4 bit ops, clear, no cursor
;output opening two-line message and wait 2 seconds to allow circuitry to stabilize.
movlw begin1text-starttext
call textout
call lcdhome2
movlw begin2text-starttext
call textout
call delay1000
call delay1000
call lcdclear ;clear lcd and display "ZERO ALL" message
movlw zerotext-starttext
call textout
;set each range and perform initial Auto-Zero for each scale (click click click)
call set1
call setstuff
call set2
call setstuff
call set3
call setstuff
call set4
call setstuff
;finished with all the initialization stuff. so here we go loop de loop!
mainloop
call periodinit ;sync and acquire a count
call checkhit ;check for buttons and process
processdata
clrf intcon ;disable interrupts (we have other work to do)
btfss flags,intoverflow ;check state of interrupt overflow flag
goto convertit ;if no overflow, convert binary, etc.
overflowed
call lcdclear ;if interrupt overflow
movlw overtext-starttext ; clear display and show message
call textout
goto mainloop ;try again!
;subroutine to check for buttons being hit while interrupts are off
gethit
comf porta,w ;copy inverted porta to w
andlw b'00011100' ;check three bits at once
btfsc status,z
return ;if all are low, then none pushed
movf porta,w
movwf acopy ;save copy of original porta for later use
;sort out the details later...
goto oldhit
;subroutine to handle buttons being hit both in and out of interrupt.
;includes immediate check and check for "old" hits registered in acopy.
checkhit
;first check for new hit key
comf porta,w ;copy inverted porta to w
andlw b'00011100' ;check three bits at once
btfsc status,z
goto oldhit ;if all are low, then none pushed
movf porta,w ;otherwise we have a new hit!
movwf acopy ;save copy of porta for later use by oldhit
;liesurely flow into oldhit routine...
oldhit
comf acopy,w ;check if a key was hit (old or new)
andlw b'00011100' ;check three bits at once
btfsc status,z
return ;if all are low, then none pushed
bcf autoflags,manual ;clear manual so we can use setx routines!
btfsc acopy,upkey ;non-inverted original in acopy. is it UP key?
goto isitdown ;1 means it was NOT UP key, so check next key
itwasup ;0 means it WAS UP key
movf offsetx,w ;ummmm, where ARE we? (what range is current?)
sublw offset1_0 ;compare by subtracting one from the other
btfss status,z ;are we at range 1?
goto upto3 ;if not, check for others...
upto2
call set2 ;if it was 1, change to range 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -