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: 2024/8/14 23:13,
3.142.12.198:LOG IN
|
©2024 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? <A HREF="http://ecomorder.com/techref/piclist/weedfreq/8digit.asm"> piclist weedfreq 8digit</A> |
Did you find what you needed? |
Welcome to ecomorder.com! |
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.