Piclist Weedfreq 8DIGIT.ASM

The Weeder Frequency Counter
Expanded by Brad Hernlem
3 byte count, 8 digits, 1Hz resolution below 16MHz
;******************************************************************************
; FREQUENCY COUNTER
; Model : WTCNT
; Author : Terry J. Weeder
; Date : November 18, 1993
; Version: 1.0
;
; WWW.WEEDTECH.COM
;
; Ported to 16f84 by
; Peter Cousens 
; October 1998
;
; Further revised,
; expanded and modified by
; Brad Hernlem
; October 2000
;******************************************************************************
; This version is changed to use the full capability to count to 3 byte
; quantities (16,777,215) and disables the overflow at 10,000,000 originally
; in Cousens' code. Also, 8 digits are used instead of seven and the gate
; times are set to 1 second to allow 1 Hz resolution on all ranges.
; When the frequency exceeds 16,777,215 Hz the gate period is 
; reduced to 0.1 second to keep the count within 3 bytes. When frequency is 
; again less than 16,777,216 Hz the gate period reverts to 1 second.
; Please also note that the register addresses are now designated in a 
; CBLOCK. This means that any changes to the CBLOCK MUST NOT affect the
; fixed addresses of the digs to digs+7 registers which SHOULD begin at
; 0C and increase from there. If these are changed, the FSR indirect 
; addressing will be munged. 
;
; Other changes:
;
; 1) the LCD control pins are reassigned to be compatible with Halicky's code
; 2) the display reads "0" when no pulses are inputted. Cousens' code included
; an rtcc toggle of unknown use which gave an output of "1" without input.
; 3) display shows message "Counting" during initial 1 second count delay.
;
; [Brad Hernlem]
;
; FCounter.ASM
;***************************************************************************
 list P=PIC16F84A
 INCLUDE <P16f84a.inc>						
	__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
rtcc equ 1h
c equ 0h
z equ 2h
o equ 7h
rs equ 0h	;This bits were changed for compatibility
rw equ 1h	;with other counter
e equ 2h	;routines (e.g. Halicky)
;Cousens had the following hard designated. CBLOCK makes them float
;but BEWARE that digs is addressed by FSR and MUST NOT be changed from
;the first position of this block
	CBLOCK	h'0C'
digs:8 			;the display digits registers digs to digs+7
count1 
count2 
addcnt 
gate 
cnt1 
cnt2 
cnt3 
calc1 
calc2 
calc3 
sum1 
sum2 
sum3 
rtcc2
temp1
temp2 
temp3
cnt4 
	ENDC
;
 org 0
 goto start
 
;
int_del movlw 0x05 ;delay 5.000 ms (4 MHz clock)
 movwf count1
d1 movlw 0xA5
 movwf count2
d2 decfsz count2,f
 goto d2
 decfsz count1,f
 goto d1
 retlw 0x00
;
lcd_out movwf PORTB ;load data into PORTB
 movlw b'00000000' ;define PORTB as output
 tris PORTB
 bsf PORTA,rs ;rs = data
 bcf PORTA,rw ;r/w = write
 bsf PORTA,e ;toggle enable
 bcf PORTA,e
 movlw b'11111111' ;define PORTB as input
 tris PORTB
 bcf PORTA,rs ;rs = instruction
 bsf PORTA,rw ;r/w = read
 bsf PORTA,e ;enable high
 movf PORTB,w ;get address counter
 movwf addcnt
 bsf addcnt,7
 bcf PORTA,e ;enable low
out1 bsf PORTA,e ;enable high
 btfss PORTB,7 ;test busy flag
 goto out2
 bcf PORTA,e ;enable low
 goto out1
out2 bcf PORTA,e ;enable low
 goto shift
;
inst movwf PORTB ;load instruction into PORTB
 movlw b'00000000' ;define PORTB as output
 tris PORTB
 bcf PORTA,rs ;rs = instruction
 bcf PORTA,rw ;r/w = write
 bsf PORTA,e ;toggle enable
 bcf PORTA,e
 movlw b'11111111' ;define PORTB as input
 tris PORTB
 bsf PORTA,rw ;r/w = read
inst1 bsf PORTA,e ;enable high
 btfss PORTB,7 ;test busy flag
 goto inst2
 bcf PORTA,e ;enable low
 goto inst1
inst2 bcf PORTA,e ;enable low
 retlw 0x00
;
shift btfss addcnt,0 ;shift to opposite side of display?
 retlw 0x00
 btfss addcnt,1
 retlw 0x00
 btfss addcnt,2
 retlw 0x00
 btfss addcnt,3
 retlw 0x00
 movlw 0x39
 addwf addcnt,f
 bsf addcnt,7
 movf addcnt,w
 goto inst
;
sub bcf STATUS,o ;clear overflow bit
 movf calc1,w ;subtract calc1 from cnt1 
 subwf cnt1,f
 btfsc STATUS,c
 goto sb1
 movlw 0x01 ;borrow from cnt2 if overflow
 subwf cnt2,f
 btfsc STATUS,c
 goto sb1
 subwf cnt3,f ;borrow from cnt3 if cnt2 overflow
 btfss STATUS,c
 bsf STATUS,o ;set overflow bit if result is negative
sb1 movf calc2,w ;subtract calc2 from cnt2
 subwf cnt2,f
 btfsc STATUS,c
 goto sb2
 movlw 0x01 ;borrow from cnt3 if cnt2 overflow
 subwf cnt3,f
 btfss STATUS,c
 bsf STATUS,o ;set overflow bit if result is negative
sb2 movf calc3,w ;subtract calc3 from cnt3
 subwf cnt3,f
 btfss STATUS,c
 bsf STATUS,o ;set overflow bit if result is negative
 retlw 0x00
;
add movf calc1,w ;add calc1 to cnt1
 addwf cnt1,f
 btfss STATUS,c
 goto ad1
 incfsz cnt2,f ;add to cnt2 if cnt1 overflow
 goto ad1
 incf cnt3,f ;add to cnt3 if cnt2 overflow
ad1 movf calc2,w ;add calc2 to cnt2
 addwf cnt2,f
 btfsc STATUS,c
 incf cnt3,f ;add to cnt3 if cnt2 overflow
 movf calc3,w ;add calc3 to cnt3
 addwf cnt3,f
 retlw 0x00
;
; The following has been modified to extract 8 digits
; and get 1 Hz accuracy up to the full 3 byte limit of 16,777,215
;
cnvt movlw 0x08 ;8 digits in display
 movwf count1
 movlw 0x0C ;set fsr for MSB in display
 movwf FSR
 movlw 0x2F ;one less that ASCII "0"
cnvt0 movwf INDF
 incf FSR,f
 decfsz count1,f
 goto cnvt0
 movlw 0x98		;load "10,000,000" in calc1-3
	movwf	calc3
	movlw	0x96
	movwf	calc2
	movlw	0x80
	movwf	calc1
cnvt1	call	sub		;subtract 10 million from count
	incf	digs,f		;increment 10,000,000s register
	btfss	STATUS,o	;check if overflow
	goto	cnvt1
	call	add		;add back last number
 movlw 0x0F ;load "1,000,000" in calc1-3
 movwf calc3
 movlw 0x42
 movwf calc2
 movlw 0x40
 movwf calc1
cnvt2 call sub ;subtract number from count
 incf digs+1,f ;increment 1,000,000's register
 btfss STATUS,o ;check if overflow
 goto cnvt2
 call add ;add back last number
 movlw 0x01 ;load "100,000" in calc1-3
 movwf calc3
 movlw 0x86
 movwf calc2
 movlw 0xA0
 movwf calc1
cnvt3 call sub ;subtract number from count
 incf digs+2,f ;increment 100,000's register
 btfss STATUS,o ;check if overflow
 goto cnvt3
 call add ;add back last number
 clrf calc3 ;load "10,000" in calc1-3
 movlw 0x27
 movwf calc2
 movlw 0x10
 movwf calc1
cnvt4 call sub ;subtract number from count
 incf digs+3,f ;increment 10,000's register
 btfss STATUS,o ;check if overflow
 goto cnvt4
 call add ;add back last number
 movlw 0x03 ;load "1,000" in calc1-3
 movwf calc2
 movlw 0xE8
 movwf calc1
cnvt5 call sub ;subtract number from count
 incf digs+4,f ;increment 1,000's register
 btfss STATUS,o ;check if overflow
 goto cnvt5
 call add ;add back last number
 clrf calc2 ;load "100" in calc1-3
 movlw 0x64
 movwf calc1
cnvt6 call sub ;subtract number from count
 incf digs+5,f ;increment 100's register
 btfss STATUS,o ;check if overflow
 goto cnvt6
 call add ;add back number
 movlw 0x0A ;load "10" in calc1-3
 movwf calc1
cnvt7 call sub ;subtract number from count
 incf digs+6,f ;increment 10's register
 btfss STATUS,o ;check if overflow
 goto cnvt7
 call add ;add back last number
 movf cnt1,w ;put remainder in 1's register
 addwf digs+7,f
 incf digs+7,f
 retlw 0x00
;
; Count period is 25*count2*count1 clocks
; for 4MHz crystal with count2=200, count1=20 gives 0.1 s gate period
; count1=200 gives 1 s gate period
;
count movlw b'00110111' ;rtcc = ext, 1/256
 option
 movlw b'00010000' ;define PORTA as output 
 tris PORTA
 bcf PORTA,3
 bcf PORTA,rs
 clrf cnt3
	clrf	cnt4
	clrf	temp3
 clrf rtcc
 clrf rtcc2
; bsf PORTA,rs ;toggle rtcc pin
; bcf PORTA,rs	 ;[these two lines were in Cousens' code. purpose unkown]
 movf gate,w ;get gate time
 movwf count1
st1 bsf PORTA,3 ;start count
fr4 movlw 0xC8		;1 count2 set to 200
 movwf count2		;2
 goto fr6		;4
fr5 nop			;24
 nop			;25
 nop			;01
 nop			;02
 nop			;03
 nop			;04
fr6 movf rtcc,w ;5 test for rtcc rollover (12)
 subwf rtcc2,f		;6
 btfss STATUS,z	;7
 goto fr7		;9
 nop			;9
 goto fr8		;11
fr7 btfsc STATUS,c	;10
 incf cnt3,f		;11
fr8 movwf rtcc2		;12
	movf	cnt3,w		;13 test for cnt3 rollover
	subwf	temp3,f		;14
	btfss	STATUS,z	;15
	goto	br1		;17
	nop			;17
	goto	br2		;19
br1	btfsc	STATUS,c	;18
	incf	cnt4,f		;19 increment cnt4 if cnt3 rollover
br2	movwf	temp3		;20
 decfsz count2,f	;21
 goto fr5		;23
 decfsz count1,f	;23+25(count2-1)
 goto fr4		;25
 bcf PORTA,3 ;25*count2*count1 stop count
st2 movf rtcc,w ;get rtcc count
 movwf cnt2
 subwf rtcc2,f ;test for rtcc rollover
 btfss STATUS,c
 goto fr9
 btfss STATUS,z
 incf cnt3,f
fr9 clrf cnt1 ;set to get prescaler count
fr10 decf cnt1,f
 bsf PORTA,rs ;toggle rtcc pin
 bcf PORTA,rs
 movf rtcc,w ;test if rtcc has changed
 xorwf cnt2,w
 btfsc STATUS,z
 goto fr10
 retlw 0x00
;
;******************************************************************************
; START
;******************************************************************************
;
start clrf PORTA ;instruction, write, enable low
 movlw b'00010000'
 tris PORTA
 clrf PORTB
 movlw b'00000000'
 tris PORTB
 call int_del
 call int_del
 call int_del
 movlw 0x38 ;initialize display
 movwf PORTB
 bsf PORTA,e ;toggle enable
 call int_del
 bcf PORTA,e
 bsf PORTA,e ;toggle enable
 call int_del
 bcf PORTA,e
 bsf PORTA,e ;toggle enable
 call int_del
 bcf PORTA,e
 movlw 0x38 ;function
 call inst
 movlw b'00001100' ;display on, cursor off
 call inst
 movlw b'00000001' ;clear display
 call inst
 movlw b'00000110' ;entry mode
 call inst
; Intro message during initial count 
 movlw 0x20		;space
	call	lcd_out
 movlw 0x20		;space
	call	lcd_out
 movlw 0x20		;space
	call	lcd_out
 movlw 0x20		;space
	call	lcd_out
 movlw 0x43		;C
	call	lcd_out
 movlw 0x6F		;0
	call	lcd_out
 movlw 0x75		;u
	call	lcd_out
 movlw 0x6E		;n
	call	lcd_out
 movlw 0x74		;t
	call	lcd_out
 movlw 0x69		;i
	call	lcd_out
 movlw 0x6E		;n
	call	lcd_out
 movlw 0x67		;g
	call	lcd_out
;
mhz movlw 0xC8 ;1 sec gate
 movwf gate
 call count
	clrw			;check whether cnt4 is zero
	xorwf	cnt4,w
	btfss	STATUS,z
	goto	shortg		;not zero - use shorter gate period
 call cnvt ;convert binary to BCD
 movlw 0x30 ;test if "0"
 xorwf digs,w
 btfss STATUS,z
 goto mhz1
 movlw 0x30 ;test if "0"
 xorwf digs+1,w
 btfsc STATUS,z
 goto khz1
mhz1 movlw 0x81 ;set display address
 call inst
 movlw 0x02 ;output first 2 characters
 movwf count1
 movlw 0x0C ;MSD of freq, i.e. digs
 movwf FSR
mhz2 movlw 0x30 ;test if "0"
 xorwf INDF,w
 btfss STATUS,z
 goto mhz3
 movlw 0x20 ;change preceeding "0's" to "space"
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto mhz2
 goto mhz4
mhz3 movf INDF,w
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto mhz3
mhz4 movlw 0x2E ;"."
 call lcd_out
 movlw 0x06 ;output last 6 characters
 movwf count1 
mhz5 movf INDF,w
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto mhz5
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x4D ;"M"
 call lcd_out
 movlw 0x48 ;"H"
 call lcd_out
 movlw 0x7A ;"z"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 goto mhz
;
khz movlw 0xC8 ;1 sec gate
 movwf gate
 call count
 call cnvt ;convert binary to BCD
 movlw 0x30 ;test if 0
 xorwf digs,w
 btfss STATUS,z
 goto mhz1
 movlw 0x32 ;test if < 2
 subwf digs+1,w
 btfsc STATUS,c
 goto mhz1
 movlw 0x30 ;test if "0"
 xorwf digs+1,w
 btfss STATUS,z
 goto khz1
 movlw 0x30 ;test if "0"
 xorwf digs+2,w
 btfss STATUS,z
 goto khz1
 movlw 0x30 ;test if "0"
 xorwf digs+3,w
 btfsc STATUS,z
 goto hz0
khz1 movlw 0x81 ;set display address
 call inst
 movlw 0x05 ;output first 5 characters
 movwf count1
 movlw 0x0C ;MSD of freq, digs register
 movwf FSR
khz2 movlw 0x30 ;test if "0"
 xorwf INDF,w
 btfss STATUS,z
 goto khz3
 movlw 0x20 ;change preceeding "0's" to "space"
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto khz2
 goto khz4
khz3 movf INDF,w
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto khz3
khz4 movlw 0x2E ;"."
 call lcd_out
 movf INDF,w ;output last 3 characters
 call lcd_out
 incf FSR,f
 movf INDF,w
 call lcd_out
 incf FSR,f
 movf INDF,w
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x4B ;"K"
 call lcd_out
 movlw 0x48 ;"H"
 call lcd_out
 movlw 0x7A ;"z"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 goto khz
;
hz movlw 0xC8 ;1 sec gate
 movwf gate
 call count
 call cnvt ;convert binary to BCD
 movlw 0x30 ;test if "0"
 xorwf digs,w
 btfss STATUS,z
 goto mhz1
 movlw 0x32 ;test if < 2
 subwf digs+1,w
 btfsc STATUS,c
 goto mhz1
 movlw 0x30 ;test if "0"
 xorwf digs+1,w
 btfss STATUS,z
 goto khz1
 movlw 0x30 ;test if "0"
 xorwf digs+2,w
 btfss STATUS,z
 goto khz1
 movlw 0x30 ;test if "0"
 xorwf digs+3,w
 btfss STATUS,z
 goto khz1
hz0 movlw 0x81 ;set display address
 call inst
 movlw 0x07 ;output first 7 characters
 movwf count1
 movlw 0x0C ;MSD of freq, digs register
 movwf FSR
hz1 movlw 0x30 ;test if "0"
 xorwf INDF,w
 btfss STATUS,z
 goto hz2
 movlw 0x20 ;change preceeding "0's" to "space"
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto hz1
 goto hz3
hz2 movf INDF,w
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto hz2
hz3	movf	INDF,w
	call	lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x48 ;"H"
 call lcd_out
 movlw 0x7A ;"z"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 goto hz
;
shortg movlw 0x14 ;0.1 sec gate
 movwf gate
 call count
	call	tenx		;multiply count by ten
	clrw			;check whether cnt4 is zero
	xorwf	cnt4,w
	btfsc	STATUS,z
	goto	mhz		;was zero - use longer gate period
 call cnvt ;convert binary to BCD
 movlw 0x30 ;test if "0"
 xorwf digs,w
 btfss STATUS,z
 goto shg1
 movlw 0x30 ;test if "0"
 xorwf digs+1,w
 btfsc STATUS,z
 goto mhz
shg1 movlw 0x81 ;set display address
 call inst
 movlw 0x03 ;output first 3 characters
 movwf count1
 movlw 0x0C ;MSD of freq, i.e. digs
 movwf FSR
shg2 movlw 0x30 ;test if "0"
 xorwf INDF,w
 btfss STATUS,z
 goto shg3
 movlw 0x20 ;change preceeding "0's" to "space"
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto shg2
 goto shg4
shg3 movf INDF,w
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto shg3
shg4 movlw 0x2E ;"."
 call lcd_out
 movlw 0x05 ;output last 5 characters
 movwf count1 
shg5 movf INDF,w
 call lcd_out
 incf FSR,f
 decfsz count1,f
 goto shg5
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x4D ;"M"
 call lcd_out
 movlw 0x48 ;"H"
 call lcd_out
 movlw 0x7A ;"z"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 movlw 0x20 ;"space"
 call lcd_out
 goto shortg
;
; This subroutine multiplies the count in cnt1-3 by 10 (called from the 0.1 sec
; gate routine) and puts any overflow into cnt4. This is to check whether the frequency
; has gone back under 16,777,216 and whether the gate period should be increased to 1 sec.
;
tenx	clrf	cnt4		;clear the overflow register and
	movf	cnt1,w		;fill calc1-3 with current cnt1-3 values
	movwf	calc1		;it is assumed that cnt4 cannot be non-zero
	movf	cnt2,w		;when the gate period is only 0.1 sec
	movwf	calc2		;
	movf	cnt3,w		;
	movwf	calc3		;
	bcf	STATUS,c
	rlf	calc1,f		;multiply by 2 and carry through
	rlf	calc2,f
	rlf	calc3,f
	btfsc	STATUS,c
	incf	cnt4,f		
	movf	calc1,w		;temporarily store the times 2 value
	movwf	temp1
	movf	calc2,w
	movwf	temp2
	movf	calc3,w
	movwf	temp3
	bcf	STATUS,c
	rlf	calc1,f		;multiply by 2 twice and check for carry each time
	rlf	calc2,f
	rlf	calc3,f
	btfsc	STATUS,c
	incf	cnt4,f
	bcf	STATUS,c
	rlf	calc1,f
	rlf	calc2,f
	rlf	calc3,f
	btfsc	STATUS,c
	incf	cnt4,f
	movf	temp1,w		;now add the x2 and x8 values for x10 total
	addwf	calc1,f
	btfsc	STATUS,c
	incf	calc2, f
	btfsc	STATUS,z
	incf	calc3,f
	btfsc	STATUS,z
	incf	cnt4,f
	movf	temp2,w
	addwf	calc2,f
	btfsc	STATUS,c
	incf	calc3,f
	btfsc	STATUS,z
	incf	cnt4,f
	movf	temp3,w
	addwf	calc3,f
	btfsc	STATUS,c
	incf	cnt4,f
	return
;
 end

file: /Techref/piclist/weedfreq/8digit.asm, 22KB, , updated: 2006年4月7日 14:43, local time: 2025年9月2日 06:11,
40.74.122.252:LOG IN

©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://techref.massmind.org/techref/piclist/weedfreq/8digit.asm"> piclist weedfreq 8digit</A>

Did you find what you needed?

Welcome to massmind.org!

Welcome to techref.massmind.org!

.

AltStyle によって変換されたページ (->オリジナル) /