TITLE
"Frequency Counter: Measures the frequency of a TTL waveform between 1
& 9999"
LIST p=PIC16F84
include "d:\mplab\p16f84.inc"
ctrval equ D'250'
;loading the counter with
250 (TMR0*Prescaler=4ms =>total 1ms)
hlfctr equ D'125'
;loading the counter with
125 (TMR0*Prescaler=4ms =>total 0.5ms)
;*****************************************************************************************************
;Needed Macros
;*****************************************************************************************************
load macro register, data
;loads
a register by a certain value
movlw data
movwf register
endm
movff macro register1, register2 ;moves
the value in register1 to register2
movf register1, w
movwf register2
endm
clrfE macro register
;clear
a 16-bit register using the most significant register
clrf register
clrf register+1
endm
incfE macro register
;increment
a 16-bit register using the most significant register
movlw D'01'
addwf register+1, F
btfsc STATUS, C
incf register,F
endm
movffE macro register1E, register2E ;moves
the value in a 16-bit register1E to a 16-bit register-2
movff register1E, register2E
movff register1E+1, register2E+1
endm
divide macro nibbles, msregister ;divide
a register into 2 other registers
movf nibbles,
W ;=>
put each nibble in a register
andlw H'0F'
movwf msregister+1
swapf nibbles, W
andlw H'0F'
movwf msregister
endm
cblock H'0C'
frequency:2, temp:2, counter, digits:4, Qstates, flags, bcd1, bcd2,
bcd3, ctr
endc
org
H'00'
goto setup
org H'04'
goto isr
table addwf PCL, F
dt H'FC', H'60', H'DA', H'F2', H'66'
dt H'B6', H'BE', H'E0', H'FE', H'F6'
dt H'00', H'CF', H'B7'
;10
for blank,11 for letter'P',12 for letter 'S'
;*********************************************************************************************************
; System Initialization
;*********************************************************************************************************
setup bsf STATUS, RP0
;select
Bank 1
load TRISB, B'00000001'
;RB7-RB6
output pins for 7-segment display,RB0\Int used for ext int
load TRISA, B'11110000'
;RA4~RA0 output pins for
Qstates
load OPTION_REG, B'11010100' ;prescaler=32,
positive edge interrupt
bcf STATUS, RP0
;select
Bank 0
load FSR, digits
;FSR
pointing to 1st digit
load Qstates, B'00001000'
;1st
digit turned on
load counter, ctrval
;counter
loaded by 250 for 1ms
clrf flags
;clear used registers
clrfE frequency
clrfE temp
clrfE digits
clrfE digits+2
call BinBCDE
load TMR0, -D'125'
;Timer0
loaded by 125 => *prescaler= 4ms
bsf INTCON, T0IE
;enable Timer0 interrupt
bsf INTCON, INTE
;enable
external interrupt
bsf INTCON, GIE
;enable
global interrupt
goto $
;*********************************************************************************************************
; Interrupt Service routine
;*********************************************************************************************************
isr btfss INTCON, T0IF
;check
the kind of interrupt (TMR0 or external)
goto extint
bcf INTCON, T0IF
;TMR0
interrupt=> clr interrupt flag
load TMR0, -D'125'
;reload
TMR0
movff Qstates, PORTA
;write to ports (displaying 1 digit)
movf INDF, W
call table
movwf PORTB
rrf Qstates, F
;moving
to next digit to the right
incf FSR, F
;FSR pointing to next digit
to the right
movlw digits+4
;checking
if no more digits to the right
subwf FSR, W
;=> 4 digits has been
displayed
btfss STATUS, Z
;=>
return to the 1st digit
goto testctr
load FSR,digits
load Qstates, B'00001000'
testctr
movlw hlfctr
;check if 0.5 sec elapsed
if so call error2
subwf counter, W
btfsc STATUS, Z
call error2
decfsz counter, F
;decrement
counter and check if counter=0
retfie
bcf flags,0
;counter=0
=> update frequency =>clear old flags
movffE temp, frequency
;update
new frequency
clrfE temp
;clear temp to start a new
count of edges
call testE
;test if frequency out of
range
btfsc flags, 0
goto error1
;frequency out of range
=> call error1
call BinBCDE
;valid
frequency => call Bin2bcdE
load counter, ctrval
;pointing
to first new digit
load FSR, digits
load Qstates, B'00001000'
retfie
error1
load digits, D'00'
;frequency
out of range
load digits+1,
D'00' ;=>
load display with word "OOPS" for 0.5 sec
load digits+2, D'11'
load digits+3, D'12'
load counter, ctrval
load FSR, digits
load Qstates, B'00001000'
retfie
error2 btfss flags, 0
;0.5
sec elapsed
return
;if freq in range => no
change =>return
load digits, D'10'
;if
freq out of range => shut down display for next 0.5 sec to flash
load digits+1, D'10'
load digits+2, D'10'
load digits+3, D'10'
load FSR, digits
load Qstates, B'00001000'
return
extint bcf INTCON, INTF
;external
interrupt => clear interrupt flag
movlw H'FF'
;check if temp:2 (16bit)
reached maximum value (2^16)
subwf temp, W
;if
temp:2 ='FFFF' no increment
btfss STATUS, Z
goto inc
movlw H'FF'
subwf temp+1, W
btfss STATUS, Z
inc incfE temp
;else increment temp:2
retfie
testE movlw B'00100111'
;check
if value in frequency > 9999 (out of range)
subwf frequency, W
;=>
set bit0 in flags to 1
btfss STATUS, C
return
btfss STATUS, Z
goto greater
movlw B'00010000'
subwf frequency+1, W
btfss STATUS, C
return
greater bsf flags, 0
return
;********************************************************************************************************
; Converts a 16-bit binary number into 4 BCD numbers stored at digits (most
signifant), digits+1,digits+2,digits+3
*********************************************************************************************************
BinBCDE movlw .16
movwf ctr
clrf bcd1
clrf bcd2
clrf bcd3
goto go
adjdec movlw 0x33
addwf bcd1, F
addwf bcd2, F
addwf bcd3, F
movlw 0x03
btfss bcd1, 3
subwf bcd1, F
btfss bcd2, 3
subwf bcd2, F
btfss bcd3, 3
subwf bcd3, F
movlw 0x30
btfss bcd1, 7
subwf bcd1, F
btfss bcd2, 7
subwf bcd2, F
btfss bcd3, 7
subwf bcd3, F
go rlf frequency+1, F
rlf frequency, F
rlf bcd3, F
rlf bcd2, F
rlf bcd1, F
decfsz ctr, F
goto adjdec
divide bcd3, digits+2
divide bcd2, digits
return
end