;
;					EJEMPLO 42
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo para MicroPIC Trainer y Micro'PIC Trainer Plus
;
;El módulo USART. Comunicación asíncrona. 
;
;El módulo USART de los dispositivos PIC16F87X incorpora el hardware necesario para implemen-
;tar comunicación serie asíncrona full-duplex o sincrona half-duplex. En este último caso el
;USART se puede comportar como Master o Slave.
;
;En los ejemplos siguientes se propone utilizar un PC para que, con el software TERMINAL.EXE,
;actúe como un simple terminal de comunicaciones. EL usuario deberá preparar los cables de
;comunicación entre la Trainer PLUS y el PC, teniendo en cuenta de cruzar las señal de
;transmisión (TxD) con la de recepción (RxD) y viceversa.
;
;Desde el terminal se desea comandar el motor DC de la tarjeta Micro'PIC I/O, según la tabla
;siguiente:
;
;		TECLA		MOVIMIENTO
;		-----		----------
;		A		Giro antihorario
;		H		Giro horario
;		P		Parada del motor
;
;El motor se conecta a las salidas RB0 y RB1. El sistema devuelve al terminal el tipo de 
;maniobra que se está realizando.

		List	p=16F873	;Tipo de procesador
		include	"P16F873.INC"	;Definiciones de registros internos

Temporal_1	equ	0x20
Temporal_2	equ	0x21		;Variables temporales

		org	0x00		;Vector de Reset
		goto	Inicio

		org	0x04		;Vector de interrupción
		goto	Inter

;******************************************************************************************
;Según el valor contenido en el registro W, se devuelve el carácter a visualizar

Tabla_Mensajes	movwf	PCL		;Calcula el desplazamiento sobre la tabla

;***********************************************************************************
;La directiva dt genera tantas intsrucciones retlw como bytes o caracteres contenga

Mens_0		equ	$		;Mens_0 apunta al primer carácter del mensaje 0
		dt	"Giro antihorario",0x0d,0x00

Mens_1		equ	$		;Mens_1 apunta al primer carácter del mensaje 1
		dt	"Giro Horario    ",0x0d,0x00

Mens_2		equ	$		;Mens_2 apunta al primer carácter del mensaje 2
		dt	"Parada del motor",0x0d,0x00

Mens_3		equ	$		;Mens_3 apunta al primer carácter del mensaje 3
		dt	"TECLA NO VALIDA ",0x0d,0x00

;*************************************************************************************
;Mensaje: Esta rutina envía vía serie RS232 el mensaje cuyo inicio está  indicado en
;el acumulador. El fin de un mensaje se determina mediante el código 0x00

Mensaje         movwf   Temporal_1      ;Salva posición de la tabla
Mensaje_1       movf    Temporal_1,W    ;Recupera posición de la tabla
                call    Tabla_Mensajes  ;Busca caracter de salida
                movwf   Temporal_2      ;Guarda el caracter
                movf    Temporal_2,F
                btfss   STATUS,Z        ;Mira si es el último
                goto    No_es_ultimo
                return
No_es_ultimo   	call    Tx_Dato		;Transmite el carácter
                incf    Temporal_1,F    ;Siguiente caracter
                goto    Mensaje_1

;********************************************************************************************
;Tx_Dato: Transmite vía serie el dato presente en el reg. W

Tx_Dato		bcf	PIR1,TXIF	;Restaura el flag del transmisor
		movwf	TXREG		;Almacena el byte a transmitir
		bsf	STATUS,RP0
Tx_Dato_Wait	btfss	TXSTA,TRMT	;Byte transmitido ??
		goto	Tx_Dato_Wait	;No, esperar
		bcf	STATUS,RP0
		return			;Si

;******************************************************************************************
;Tratamiento de la interrupción

Inter		btfss	PIR1,RCIF	;Ha sido interrupción en la recepción ??
		retfie			;No, falsa interrupción
		bcf	PIR1,RCIF	;Si, restaurar el flag de interrupción
		movlw	'A'
		subwf	RCREG,W
		btfsc	STATUS,Z	;A sido la tecla A ??
		goto	Giro_A		;Si
		movlw	'H'
		subwf	RCREG,W		
		btfsc	STATUS,Z	;A sido la tecla H ??
		goto	Giro_H		;Si
		movlw	'P'
		subwf	RCREG,W		
		btfsc	STATUS,Z	;A sido la tecla P ??
		goto	Parada		;Si

		movlw	Mens_3		;Visualiza Mens_3 "TECLA NO VALIDA"
Inter_Fin	call	Mensaje		;Salida del mensaje
		retfie

Giro_A		movlw	b'00000010'
		movwf	PORTB		;Giro antihorario
		movlw	Mens_0		;Visualiza Mens_0 "Giro antihorario"
		goto	Inter_Fin
Giro_H		movlw	b'00000001'
		movwf	PORTB		;Giro horario
		movlw	Mens_1		;Visualiza Mens_1 "Giro Horario"
		goto	Inter_Fin
Parada		clrf	PORTB		;Para el motor
		movlw	Mens_2		;Visualiza Mens_2 "Parada del motor"
		goto	Inter_Fin

;*******************************************************************************************
;Programa principal

Inicio	     	clrwdt
		clrf	PORTC		
		clrf	PORTB
		bsf	STATUS,RP0	;Selecciona banco 1
		clrf	PORTB		;Puerta B salida
		movlw	b'10111111'
		movwf	TRISC		;RC7/Rx entrada, RC6/Tx salida
		movlw	b'11001111'
		movwf	OPTION_REG	;Preescaler de 128 asociado al WDT

		movlw	b'00100100'	
		movwf	TXSTA		;TX en On, modo asíncrono con 8 bits y alta velocidad
		movlw	.25
		movwf	SPBRG		;9600 baudios con Fosc=4MHz
		bsf	PIE1,RCIE	;Habilita interrupción en la recepción
		bcf	STATUS,RP0	;Selecciona banco 0
		
		movlw	b'10010000'
		movwf	RCSTA		;USART en On, recepción contínua
		bsf	INTCON,PEIE	;Activa interrupción de periféricos
		bsf	INTCON,GIE	;Activa interrupciones

Loop		clrwdt
		goto	Loop

		end			;Fin del programa fuente
