;
;					EJEMPLO 6
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo MicroPIC Trainer y Micro'PIC IO
;
;El TMR1 en el modo contador. Frecuencímetro
;
;Mediante el generador de onda cuadrada de la tarjeta Micro'PIC IO, 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

		org	0x00		;Vector de Reset
		goto	Inicio

		org	0x04		;Vector de interrupción
		goto	Inter

		include	"LCD_CXX.INC"	;Incluye rutinas de manejo del LCD

;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_DATO	;Lo visualiza
		movf	INDF,W
		andlw	0x0f
		iorlw	0x30		;Convierte a ASCII el nible de menos peso
		call	LCD_DATO	;Lo visualiza
		decf	FSR,F		;Siguiente byte
		decfsz	Contador,F
		goto	Visual_loop
		return

;16Bits_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.
;Está presentada en la nota de aplicación AN544 de MICROCHIP y 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

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

Inter		decfsz	Delay,F		;Han pasado 50 mS ??
		goto	No_250_mS	;No
Si_250_mS	bcf	T1CON,0		;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	.5
		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
		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
		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		

		end			;Fin del programa fuente
