Bueno, en tu caso, donde hay sólo un Timer, las cosas se ponen complicadas. Sinceramente te recomendaría que migraras a otro microcontrolador similar pero que posea mayor cantidad de Timers y los periféricos que necesitas. Hay infinidad en la familia 16F que cumplen con estos requisitos.
Si es por el mero desafío o aprendizaje, hay tantas formas de abordar el problema como ingenio y conocimientos se tengan, tanto continuando usando las interrupciones, como no usándolas. Sin embargo, todas involucran un estricto control de los ciclos de ejecución y de un pre-cálculo de los posibles procesos que pudiesen ocurrir durante la ejecución mísma.
Por ejemplo, nada impide que tengas el mísmo algorítmo de antes, sólo que el algoritmo de demora deberá tener en cuenta ciertos factores.
Supongamos que queremos determinar la frecuencia basados en un tiempo de 100ms(en lugar de 250ms):
Para ello, el algoritmo de demora podría utilizar una dos variables de 8 bits trabajando como una de 16 bits(nuestro contador de ciclos / 2).
Lo pre-cargaríamos entonces con un valor poco menor a 100000 / 2 (0xC350). E implementaríamos un bucle sencillo que iría descontando a partir de allí:
El error de cálculo del algoritmo se deberá al error introducido por el cristal externo y por la señal de entrada.
Se podría mejorar el bucle en un par de instrucciones, pero puede que ya sea demasiado fanatismo hacerlo, así que no lo hice.
;====================================================================
; Main.asm file generated by New Project wizard
;
; Created: sáb sep 14 2013
; Processor: PIC16F84A
; Compiler: MPASM (Proteus)
;====================================================================
;====================================================================
; DEFINITIONS
;====================================================================
#include p16f84a.inc ; Include register definition file
;#include lib_lcd.inc ; Incluyo la libreria lcd
;====================================================================
; Opciones
;====================================================================
__config _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
;====================================================================
; VARIABLES
;====================================================================
PULSOS equ 0x11
V_TMR0 equ 0x12
delayl equ 0x13
delayh equ 0x14
aux equ 0x15
;Define
#DEFINE IN_OUT_DELAY .9 ;ciclos de demora introducidos por el call, return, cierre de NAND deben ser tenidos en cuenta)
#DEFINE CYCLES (.50000 - IN_OUT_DELAY)
;====================================================================
; RESET and INTERRUPT VECTORS
;====================================================================
; Reset Vector
RST code 0x0
goto Start
ISR org 0x4
incf PULSOS,F
retfie
PGM code
FRECUENCIA
;Operaciones
return
errorlevel -302
Start
;Incializamos el LCD
;call initlcd
;Incializamos las interrupciones
bsf STATUS,RP0 ; Paso al banco 1
movlw b'11101000'
movwf OPTION_REG ; Configuro el registro de opciones Preescaler a 000
movlw b'10000'
movwf TRISA
bcf STATUS,RP0 ; Vuelvo al banco 0
;LCD_PUTC 'F'
;LCD_PUTC 'R'
;LCD_PUTC 'E'
;LCD_PUTC 'C'
;LCD_PUTC 'U'
;LCD_PUTC 'E'
;LCD_PUTC 'N'
;LCD_PUTC 'C'
;LCD_PUTC 'I'
;LCD_PUTC 'M'
;LCD_PUTC 'E'
;LCD_PUTC 'T'
;LCD_PUTC 'R'
;LCD_PUTC 'O'
bcf PORTA,3 ; Cierro la entrada de frecuencia
;bsf INTCON,7 ; Activo las interrupciones globales
;bsf INTCON,5 ; Activo la interrupcion del TMR0 por desbordamiento
reiniciar
clrf PULSOS
movlw HIGH CYCLES
movwf delayh
movlw LOW CYCLES
movwf delayl
clrf TMR0
bcf INTCON,T0IF
open
bsf PORTA,3 ; Abro la entrada de frecuencia
call retardo_100ms
close
goto $+1
goto $+1
goto $+1
goto $+1
goto $+1
nop
bcf PORTA,3 ; Cierro la entrada de frecuencia
btfsc INTCON,T0IF ;caso extraño, pero puede ocurrir
incf PULSOS,F
movf TMR0,W ; Muevo al registro W
movwf V_TMR0 ; Almaceno el valor que hay en TMR0
goto reiniciar
;====================================================================
; Subrutinas
;====================================================================
retardo_100ms
movf INTCON,W
movwf aux
movlw .8 ;demora básica bucle
btfsc aux,T0IF
incf PULSOS,F
btfsc aux,T0IF
bcf INTCON,T0IF ;limpiar flag de interr.
nop ; para hacer par la cantidad de instrucciones del bucle
subwf delayl,F
btfsc STATUS,C
goto noCarry
movlw .1
subwf delayh,F
btfsc STATUS,C
goto retardo_100ms
return
noCarry ;compensar ciclos hasta llegar a 16 (8 x 2)
goto $+1 ; 2 ciclos
goto retardo_100ms ; 2 ciclos
;====================================================================
END
Saludos.