Hola muchachos, estaba recordando y leyendo algunas cosas de los timer como contadores con instrucciones en ASM y me topo con este programita.... Pero no logro captar un pedacito del programa, en especifico es la parte que está en rojo:
El programa es de los ejemplos de la MICROCHIP, y es el siguiente:
PRACTICA 10
;
; Autor: Mikel Etxebarria
; (c) Microsystems Engineering (Bilbao)
;
;El TMR1 en el modo contador. Frecuencímetro
;
;Mediante el generador de onda cuadrada del entrenador, se aplican pulsos por la línea RC0/T1CKI.
;
;El TMR1 cuenta los pulsos durante un intervalo de 0.250 s. Al resultado de la cuenta se
;multiplica por 4 y se obtiene el número de pulsos por segundo o herzios.
;
;Dicha frecuencia se visualiza por la pantalla LCD de la tarjeta Micro'PIC Trainer.
List p=16F873 ;Tipo de procesador
include "P16F873.INC" ;Definiciones de registros internos
Lcd_var equ 0x20 ;Inicio de variables de las rutinas LCD
Byte_L equ 0x22 ;Parte baja del byte a convertir
Byte_H equ 0x23 ;Parte alta del byte a convertir
BCD_2 equ 0x24 ;Byte 2 de conversión a BCD
BCD_1 equ 0x25 ;Byte 1 de conversión a BCD
BCD_0 equ 0x26 ;Byte 0 de conversión a BCD
Contador equ 0x27 ;Variable de contaje
Temporal equ 0x28 ;Variable temporal
Delay equ 0x29 ;Variable para la temporización
DATO_A equ 0x30
DATO_B equ 0x31
org 0x00 ;Vector de Reset
goto Inicio
org 0x04 ;Vector de interrupción
goto Inter
;******************************************************************************************
;Visualizar: Visualiza sobre la pantalla LCD los cinco dígitos situados en las variables
;BCD_0, BC_1 y BCD_2
Visualizar movlw 0x80
call LCD_REG ;Posiciona el cursor
movlw 3
movwf Contador ;Inicia contador de bytes a convertir
movlw BCD_0
movwf FSR ;Inicia puntero índice
Visual_loop swapf INDF,W
andlw 0x0f
iorlw 0x30 ;Convierte a ASCII el nible de más peso
call LCD_DATOS ;Lo visualiza
movf INDF,W
andlw 0x0f
iorlw 0x30 ;Convierte a ASCII el nible de menos peso
call LCD_DATOS ;Lo visualiza
decf FSR,F ;Siguiente byte
decfsz Contador,F
goto Visual_loop
movlw ' '
call LCD_DATOS
movlw 'P'
call LCD_DATOS
movlw 'P'
call LCD_DATOS
movlw 'M'
call LCD_DATOS
return
;****************************************************************************************
;Bits16_BCD: Esta rutina convierte un número binario de 16 bits situado en Cont_H y
;Cont_L y lo convierte en 5 dígitos BCD que se depositan en las variables BCD_0, BCD_1
;y BCD_2, siendo esta última la de menos peso.
;Esta rutina se presenta en la nota de aplicación AN544 de MICROCHIP y está adaptada por
;Microsystems Engineering
Bits16_BCD bcf STATUS,C
clrf Contador
bsf Contador,4 ;Carga el contador con 16
clrf BCD_0
clrf BCD_1
clrf BCD_2 ;Puesta a 0 inicial del resultado
Loop_16 rlf Byte_L,F
rlf Byte_H,F
rlf BCD_2,F
rlf BCD_1,F
rlf BCD_0,F ;Desplaza a izda. (multiplica por 2)
decfsz Contador,F
goto Ajuste
return
Ajuste movlw BCD_2
movwf FSR ;Inicia el índice
call Ajuste_BCD ;Ajusta el primer byte
incf FSR,F
call Ajuste_BCD ;Ajusta el segundo byte
incf FSR,F
call Ajuste_BCD
goto Loop_16
Ajuste_BCD movf INDF,W
addlw 0x03
movwf Temporal
btfsc Temporal,3 ;Mayor de 7 el nibble de menos peso ??
movwf INDF ;Si, lo acumula
movf INDF,W
addlw 0x30
movwf Temporal
btfsc Temporal,7 ;Mayor de 7 el nibble de menos peso ??
movwf INDF ;Si, lo acumula
return
;********************************************************************************************
;Programa de tratamiento de la interrupción que se provoca cuando el TMR0 temporice 50mS.
;Trabajando a 4MHz el TMR0 evoluciona cada 1 uS. Con un preescaler de 256, hay que cargar
;el valor 195 para provocar una interrupción cada 50 mS. Esta temporización se repite 5 veces
;para conseguir un delay de 250 mS, al final de los cuales se captura el contenido del TMR1.
Inter decfsz Delay,F ;Han pasado 250 mS ??
goto No_250_mS ;No
Si_250_mS bcf T1CON,0 ;Si, TMR1 en Off, cuenta detenida
bcf STATUS,C
rlf TMR1L,F
rlf TMR1H,F
rlf TMR1L,F
rlf TMR1H,F ;Multiplica por 4 el valor del TMR1
movf TMR1L,W
movwf Byte_L ;Salva parte baja del contador
movf TMR1H,W
movwf Byte_H ;Salva parta alta del contador
call Bits16_BCD ;Convierte a BCD el resultado de la cuenta
call Visualizar ;Visualiza el resultado
movlw ~.195
movwf TMR0
movlw .20
movwf Delay ;Repone para temporizar cada 250mS
bcf INTCON,2 ;Repone flag del TMR0
clrf TMR1L
clrf TMR1H ;Borra el TMR1
bsf T1CON,0 ;TMR1 en On, se inicia la cuenta
retfie
No_250_mS movlw ~.195
movwf TMR0 ;Repone para temporizar otros 50mS
bcf INTCON,2 ;Repone el flag del TMR0
retfie
;Programa principal
Inicio clrf PORTB ;Borra los latch de salida
clrf PORTA ;Borra los latch de salida
bsf STATUS,RP0 ;Selecciona banco 1
movlw b'00000110'
movwf ADCON1 ;Puerta A E/S digitales
clrf TRISB ;Puerta B se configura como salida
clrf TRISA ;Puerta A se configura como salida
movlw b'11000111'
movwf OPTION_REG ;Preescaler de 256 asociado al TMR0
movlw 0xff
movwf TRISC ;Puerta C como entrada
bcf STATUS,RP0 ;Selecciona banco 0
;El TMR1 actúa como contador externo asíncrono y con un preescaler de 1:1
movlw b'00000010'
movwf T1CON ;TMR1 Off
clrf TMR1L
clrf TMR1H ;Puesta a 0 del TMR1
call UP_LCD ;Configura puerto para el LCD
call LCD_INI ;Inicia el LCD
movlw b'00001100'
call LCD_REG ;LCD On, cursor y blink Off
movlw ~.195
movwf TMR0
bsf T1CON,0 ;TMR1 en On, comienza la cuenta de pulsos externos
movlw .5
movwf Delay ;Prepara temporización de 250mS
movlw b'10100000'
movwf INTCON ;Habilita interrupción del TMR0
Loop clrwdt ;Refresca el WDT
nop
goto Loop ;Bucle infinito
;--------------------------rutina para encender la PANTALLA LCD------------------------
UP_LCD nop
bsf STATUS,5 ;Banco 1
bcf STATUS,6 ;seleccion del BANCO1
movlw 0x8E ;cargo en W el dato 0x06
movwf ADCON1 ;configuro el Puerto A como E/S Digitales
clrf TRISA ;Puerta A salida
clrf TRISB ;Puerta B salida
bcf STATUS,5 ;Banco 0
bcf STATUS,6 ;Banco 0
clrf PORTA ;reset puerta A
clrf PORTB ;reset puerta B
clrf INTCON ;Desactivar interrupciones.
bcf PORTA,3 ;RS=0
bcf PORTA,2 ;E=0 Desactiva LCD
return
;-----------------------------RUTINA LCD-------------------------------------------
;LCD_BUSY: Lectura del Flag busy & direcci¢n.
;
LCD_BUSY bsf PORTA,1 ;Pone el LCD en modo lectura
bsf STATUS,5 ;Selecciona el banco 1
bcf STATUS,6
movlw 0xff
movwf TRISB ;Puerta B como entrada
bcf STATUS,5 ;Selecciona el banco 0
bcf STATUS,6
bsf PORTA,2 ;Activa el LCD
nop
L_BUSY btfsc PORTB,7 ;Chequea bit de Busy
goto L_BUSY
bcf PORTA,2 ;Desactiva LCD
bsf STATUS,5 ;Selecciona banco 1
clrf TRISB ;Puerta B salida
bcf STATUS,5 ;Selecciona el banco 0
bcf PORTA,1 ;Pone LCD en modo WR
return
;-------------------------------------------------------------------------
;LCD_E: Pulso de Enable
;
LCD_E bsf PORTA,2 ;Activa se¤al E
nop ;Espera 1 uS
bcf PORTA,2 ;Desactiva se¤al E
return
;
;-------------------------------------------------------------------------
;LCD_DATO: Escritura de datos en DDRAM o CGRAM
;
LCD_DATOS bcf PORTA,3 ;Desactiva RS (modo comando)
movwf PORTB ;Valor ASCII a sacar por RB
call LCD_BUSY ;Espera a que se libere el LCD
bsf PORTA,3 ;Activa RS (modo dato).
goto LCD_E ;Genera pulso en la se¤al E
;------------------------------------------------------------------------
;LCD_REG: Escritura de comandos en el LCD
;
LCD_REG bcf PORTA,3 ;Desactiva RS (modo comando)
movwf PORTB ;Saca el c¢digo de la instrucci¢n
call LCD_BUSY ;Espera se libere el LCD
goto LCD_E ;Genera pulso en la se¤al E
;
;------------------------------------------------------------------------
;LCD_INI: Inicializaci¢n del LCD
;
LCD_INI movlw b'00111000' ;Caracteres 5-7,datos de 8 bits.
call LCD_REG ;C¢digo de instrucci¢n
call DELAY_5MS ;5ms.(Especificaci¢n de Fabricante)
movlw b'00111000'
call LCD_REG ;C¢digo de instrucci¢n
call DELAY_5MS ;5ms.(Especificaci¢n de Fabricante)
movlw b'00111000'
call LCD_REG ;C¢digo de instrucci¢n
call DELAY_5MS ;5ms.(Especificaci¢n de Fabricante)
return
;--------------------------FIN RUTINA LCD--------------------------------
;------------------------------------------------------------------------
;DELAY_5MS: Genera una temporizaci¢n de 5 mS
;
DELAY_5MS movlw 0x1a
movwf DATO_B ;Carga la variable DATO_B
clrf DATO_A ;Carga la variable DATO_A
DELAY_1 decfsz DATO_A,1 ;Decrementa la variable DATO_A
goto DELAY_1
decfsz DATO_B,1 ;Decrementa la variable DATO_B
goto DELAY_1
return
;------------------------------------------------------------------------
;-----------------------------RUTINA DE TEMPORIZACION--------------------
DELAY call DELAY_5MS ;demora de 25_ms.
call DELAY_5MS
call DELAY_5MS
call DELAY_5MS
call DELAY_5MS
return
DELAY1 call DELAY ;demora de 100_ms.
call DELAY
call DELAY
call DELAY
return
DELAY2 call DELAY1 ;demora de 500_ms.
call DELAY1
call DELAY1
call DELAY1
call DELAY1
return
end ;Fin del programa fuente
Esa parte roja, me dice que al desplazar los registros del timer 1 a la derecha me está multiplicando por 4 el contenido del timer 1, ahora esa es mi duda, como me multiplica por 4 rotando los bits de dichos registros...????
Si alguien pudiera explicarme se lo agradeceria, porque me he quedado con esta duda de este programa!!!! Gracias de antemano!
Atte: Enigma... La llanerita de Guayana