Buenas a todos, tengo el siguiente código que consiste en simplemente encender y apagar un led cada 0.5 segundos en el PICF84A , pero lo necesito usando un TMR0 como temporizador, si alguien sabe como se lo agradecería
LIST P=16F84A
INCLUDE
CBLOCK 0x0C ; In this position starts user´s RAM.
ENDC
.#DEFINE LED PORTB,0
;***************************************************************************************** ORG 0x00
INICIO
bsf STATUS,RP0............................................................; Access to bank 1
bcf LED .........................................................................; LED line configurated like OUTPUT
bcf STATUS,RP0 ..........................................................; Access to Bank 0.
PRINCIPAL
bsf LED .........................................................................; Turn on the LED
call Retardo_200ms ......................................................; while the sum of this time
call Retardo_200ms
bcf LED ..........................................................................; It turns off while the sum of the next retardos
call Retardo_200ms
call Retardo_100ms
goto PRINCIPAL
; Subrutinas "Retardo_200ms" y "Retardo_100ms"-------------------------------------------
CBLOCK
R_ContA ......................................................................; Counters for the retardos
R_ContB
ENDC
Retardo_200ms ...........................................................; The named "call" aports 2 machine cycles.
movlw d'200' ................................................................; It Aports 1 machine cycle. This is the value of "M".
goto Retardos_ms ........................................................; It aports 2 machine cycles.
Retardo_100ms ............................................................; The named "call" aports 2 machine cycles.
movlw d'100' ................................................................; It aports 1 machine cycle.This is the value of "M".
goto Retardos_ms ........................................................; It aport 2 machine cycles.
Retardo_1ms ...............................................................; The named "call" aports 2 machine cycles.
movlw d'1' ....................................................................; It aports 1 machine cycle. This is the value of "M".
Retardos_ms
movwf R_ContB .......................................................; It aports 1 machine cycle.
R1ms_BucleExterno
movlw d'249' .......................................................; It aports Mx1 machine cycles. This is the value of "K".
movwf R_ContA .......................................................; It aports Mx1 machine cycles.
R1ms_BucleInterno
nop ; It aports KxMx1 machine cycles.
decfsz R_ContA,F .....................................................; (K-1)xMx1 cm (when it doesn´t jump) + Mx2 cm (when it jumps).
goto R1ms_BucleInterno .................................................; It aports (K-1)xMx2 machine cycles.
decfsz R_ContB,F .......................................................; (M-1)x1 cm (when it doesn´t jump) + 2 cm (when it jumps).
goto R1ms_BucleExterno ................................................; It aports (M-1)x2 machine cycles.
return.................................................................; The return Jump aports 2 machine cycles.
END
Hola,
Tu código actual hace el retardo «a mano», con bucles de nop contando ciclos de instrucción. Con TMR0 la idea cambia: dejas que el hardware del PIC cuente por ti, y tu programa solo comprueba periódicamente si ya ha desbordado.
Primero, en el banco 1, configuras OPTION_REG para que TMR0 use el reloj interno con el prescaler más alto (1:256), que es el que te da retardos más largos antes de desbordar:
bsf STATUS,RP0
movlw B'00000111' ; TMR0 con reloj interno, prescaler asignado a TMR0, division 1:256
movwf OPTION_REG
bcf STATUS,RP0
Con un cristal de 4MHz (el más habitual con el 16F84A), cada ciclo de instrucción dura 1µs. Con el prescaler a 1:256, TMR0 se incrementa cada 256µs, y como es un registro de 8 bits, desborda (pasa de 255 a 0 y activa el flag T0IF) cada 256 incrementos, es decir, aproximadamente cada 256 × 256µs ≈ 65,5ms.
Para llegar a 0.5 segundos, cuentas cuántos desbordamientos hacen falta (500ms ÷ 65,5ms ≈ 8 desbordamientos) y esperas ese número de veces:
Retardo_500ms
movlw d'8' ; numero de desbordamientos necesarios, ajustalo a tu cristal real
movwf ContOverflow
EsperaOverflow
bcf INTCON,T0IF ; limpiamos el flag antes de esperar el siguiente
CheckFlag
btfss INTCON,T0IF ; esperamos a que TMR0 desborde
goto CheckFlag
decfsz ContOverflow,F
goto EsperaOverflow
return
Y en tu bucle principal, sustituyes las llamadas a los Retardo_200ms/Retardo_100ms por una única llamada a Retardo_500ms:
PRINCIPAL
bsf LED
call Retardo_500ms
bcf LED
call Retardo_500ms
goto PRINCIPAL
El valor d'8' de ContOverflow depende de la frecuencia real de tu cristal, si no es de 4MHz, recalcula cuánto tarda cada desbordamiento con tu frecuencia real y ajusta el número de vueltas. Este enfoque por polling (comprobar el flag en un bucle) es el más simple de entender; si más adelante necesitas que el PIC haga otras cosas mientras espera, la evolución natural es usar el TMR0 con interrupción real en vez de sondear el flag a mano, pero para encender/apagar un LED sin más lógica de por medio, el polling es perfectamente válido y más fácil de depurar.
David Carrero