;
;					EJEMPLO 20
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo MicroPIC Trainer y Micro'PIC I/O
;
;Los módulos CCPx. Modo PWM y modo comparación.
;
;Existen 2 módulos CCP que puede emplearse simultáneamente. El CCP1 se empleará en el modo de
;comparación y el CCP2 en el modo PWM.
;
;El ejemplo siguiente propone realizar una secuencia de movimiento del motor de la tarjeta
;Micro'PIC I/O. El módulo CCP2, mediante su salida por RC1/CCP2 aplica PWM para gobernar la
;velocidad. El encoder genera pulsos que denotan el giro del motor. Estos se aplican a la 
;línea RC0/T0CKI para ser comparados por el módulo CCP1. RB0 y RB1 controlan el sentido de
;giro.
;
;La secuencia de movimiento es la siguiente:
;
;1.- El motor arranca suavemente en sentido horario hasta llegar a la velocidad máxima.
;2.- Gira en sentido horario tantos pasos como determinen la constante "Horario".
;3.- Parada de 1 segundo
;4.- Giro anti horario tantos pasos indique la variable "Antihorario" a la velocidad determina
;    por los interruptores (RA4-RA0)*8.
;5.- En sentido anti horario la velocidad decrece hasta llegar a detener el motor
;6.- Parada de 1 segundo y vuelta a repetir la secuencia.

		List	p=16F873	;Tipo de procesador
		include	"P16F873.INC"	;Definiciones de registros internos

Horario		equ	.1500		;Nº de pasos en sentido horario
Antihorario	equ	.1000		;Nº de pasos en sentido anti horario
Periodo		equ	.255		;Periodo de 255*Preescaler de 16 (4mS)

Temporal	equ	0x20		;Variable temporal
Delay_Cont	equ	0x21		;Variable de temporización

		org	0x00		;Vector de Reset
		goto	Inicio

		org	0x05		;Salva el vector de interrupción

;Delay. Esta rutina genera una temporización nominal de 20mS que se repite tantas veces
;como indique la variable Delay_Cont. El TMR0, con un preescaler de 256, se carga con 78. 
;Trabajando a 4 MHz evoluciona cada 1 uS. La temporización total es de unos 20mS * Delay_Cont

Delay		movlw	~.78
		movwf	TMR0		;Inicia el TMR0
Delay_1		clrwdt			;Refrescar el WDT
		btfss	INTCON,T0IF	;Han pasado 20 mS ??
		goto	Delay_1	;Todavía no
		bcf	INTCON,T0IF	;Si, reponer el flag del TMR0
		decfsz	Delay_Cont,F	;Se ha repetido tantas veces indique Delay_Cont ??
		goto	Delay		;Todavía no, repetir otros 20 mS
		return			;Si, fin de temporización

;Programa principal

Inicio	        clrf	PORTA
		clrf	PORTB
		clrf	PORTC		;Borra salidas
		bsf	STATUS,RP0	;Selecciona banco 1
		movlw	b'00000110'
		movwf	ADCON1		;Puerta A E/S digitales
		clrf	TRISB		;Puerta B se configura como salida
		movlw	b'00011111'
		movwf	TRISA		;RA4-RA0 entradas
		movlw	b'11111101'
		movwf	TRISC		;RC1 salida, RC0 entrada
		movlw	b'11000111'
		movwf	OPTION_REG	;Preescaler de 256 asociado al TMR0
		movlw	Periodo-1
		movwf	PR2		;Carga el registro de periodos
		bcf	STATUS,RP0	;Selecciona banco 0

;El módulo CCP2 actúa en el modo PWM con salida de señal por RC1/CCP2

Loop		clrwdt			;Refrescar el WDT
		movlw	b'00001100'
		movwf	CCP2CON

		movlw	.255
		movwf	Temporal	;Máxima velocidad deseada
		clrf	CCPR2L		;Velocidad inicial nula

;El TMR2 trabaja con un preescaler 1:16 por lo que con una frecuencia de 4MHz evoluciona
;cada 16 uS (4*Tosc)*16

		movlw	b'00000111'
		movwf	T2CON		;T2 en On

;Paso_1: Desde velocidad 0, incrementarla hasta llegar a la máxima girando en sentido horario

		movlw	b'00000010'
		movwf	PORTB		;Giro horario

Paso_1		movlw	2
		movwf	Delay_Cont
		call	Delay		;Temporiza 40 ms
		incf	CCPR2L,F	;Incrementa la velocidad aumentando la anchura "Duty"
		decfsz	Temporal,F	;Ha llegado a la máxima ??
		goto	Paso_1		;No, seguir aumentando
	
;Paso_2: Se avanza en sentido horario tantos pasos indique "Horario
		
		clrf	TMR1L
		clrf	TMR1H		;Inicia el TMR1
		movlw	high Horario
		movwf	CCPR1H
		movlw	low Horario
		movwf	CCPR1L		;Inicia contador de pasos a dar en sentido horario

		movlw	b'00001011'
		movwf	CCP1CON		;Módulo CCP1 en modo comparación con reset del TMR1

		movlw	b'00000011'
		movwf	T1CON		;TMR1 preescaler 1:1, clock externo por RC0/T1CKI, On
		bcf	PIR1,CCP1IF	;Repone el flag del módulo CCP1
Paso_2_1	clrwdt
		btfss	PIR1,CCP1IF	;Se han dado los pasos en sentido horario ??
		goto	Paso_2_1	;Todavía no
		bcf	PIR1,CCP1IF	;Si, reponer el flag del módulo CCP1
		clrf	PORTB		;Desconectar motor

;Paso_3: Parada de 1 segundo
		
Paso_3		movlw	.50
		movwf	Delay_Cont
		call	Delay		;Temporiza 1 segundo

;Paso_4: Giro anti-horario tantas veces indique la variable "Antihorario" a la velocidad
;determinada por (RA4-RA0)*8

Paso_4		movlw	High Antihorario
		movwf	CCPR1H
		movlw	Low Antihorario
		movwf	CCPR1L		;Carga Nº de pasos anti-horario
		
		movf	PORTA,W
		movwf	Temporal	;Lee el estado de RA4-RA0
		bcf	STATUS,C
		rlf	Temporal,F
		rlf	Temporal,F
		rlf	Temporal,W	;Multiplica por 8
		movwf	CCPR2L		;Carga el registro de anchura "Duty"

		movlw	b'00000001'
		movwf	PORTB		;Giro anti-horario del motor

Paso_4_1	clrwdt
		btfss	PIR1,CCP1IF	;Se han dado los pasos ??
		goto	Paso_4_1	;No, esperar
		bcf	PIR1,CCP1IF	;Reponer el flag del módulo CCP1
		
;Paso_5: La velocidad decrece hasta llegar a la mínima
		
Paso_5		movlw	.2
		movwf	Delay_Cont
		call	Delay		;Temporiza 40 mS
		decfsz	CCPR2L,F	;Disminuye anchura "Duty" (velocidad). Es la mínima ??
		goto	Paso_5		;No, sigue decreciendo

;Paso_6: El motor se para y se temporiza 1 segundo. Se repite todo el ciclo
		
Paso_6		clrf	PORTB		;Parada del motor
		movlw	.50
		movwf	Delay_Cont
		call	Delay		;Temporiza 1 segundo
		goto	Loop		;Repetir el ciclo

		end			;Fin del programa fuente
