
;El programa principal que utilize estas rutinas tiene que 
;cargar las siguientes constantes:
;
;CLKIN:		Frecuencia del oscilador expresada en ciclos/segundo
;BAUDIOS:	Frecuencia a la que se desea comunicar
;T_MODO:	Modo de transmisión, a "1" se transmite primero el bit LSB, a "0" el MSB
;R_MODO:	Modo de recepción, a "1" se recibe primero el bit LSB, a "0" el MSB
;T_Nbit:	Número de bits a transmitir, 7 u 8
;R_Nbit:	Número de bits a recibir, 7 u 8
;Sbit:		Número de bits de stop, 1 o 2
;						
;
CLKOUT		equ	CLKIN >> 2	;Calcula duración del ciclo máquina
DELAY		equ	((CLKOUT/BAUDIOS)/3)-.5	;Calcula la duración del bit
DELAY_L		equ	low	DELAY	;Calcula la parte baja de DELAY
DELAY_H		equ	high DELAY+1	;Calcula la parte alta de DELAY
DELAY_START	equ	(DELAY/2)+DELAY	;Calcula duración del bit de inicio
DELAY_START_L	equ	low DELAY_START	;Calcula parte baja de DELAY_START
DELAY_START_H	equ	high DELAY_START+1	;Calcula parte alta de DELAY_START

;El programa principal que utilize estas rutinas tiene que 
;reservar 5 posiciones de la memoria de datos para el siguiente
;bloque de registros con el nombre "Rs_232_var" 

		CBLOCK	Rs232_var	;Reserva de memoria. Inicio de las variables
		Rxdreg			;Registro de recepción
		Txdreg			;Registro de transmisión
		Cont			;Contador de bits transmitidos
		Dlycnt_l		;Contador de delay parte baja
		Dlycnt_h		;Contador de delay parte alta
		ENDC

#define		Txd_pin	PORTB,4		;Línea de transmisión
#define		Rxd_pin	PORTB,5		;Línea de recepción
			
;***********************************************************************************
;RxD: Rutina de recepción. Trás detectar el bit de inicio, espera recibirse una
;palabra de 7 u 8 bits según la variable R_Nbit. Se recibe primero el bit de más peso
;o el de menos peso según la variable R_MODO

RxD		clrf	Rxdreg		;Borrar registro receptor
RxD_1		clrwdt			;Refresco del WDT
		btfsc	Rxd_pin
		goto	RxD_1		;Espera el bit de inicio ("0")
		call	Delay_ini	;Tiempo de retraso del bit de inicio (1.5 del resto
					;de los bits)
													
		IF	R_Nbit == 8
		movlw	8		;8 bits de datos
		ELSE
		movlw	7		;7 bits de datos
		ENDIF
			
		movwf	Cont
RxD_next	bcf	STATUS,C
		IF	R_MODO == 1
		rrf	Rxdreg,F	;Recibir primero el bit de menos peso
		ELSE
		rlf	Rxdreg,F	;Recibir primero el bit de más peso
		ENDIF
				
		btfsc	Rxd_pin     	;Chequea bit de entrada y mira si es "1"
		IF	R_MODO == 1
		IF	R_Nbit == 8
		bsf	Rxdreg,7    	;Activa bit 7 de Rxdreg si nºbits=8 y 1º bit LSB
		ELSE
		bsf	Rxdreg,6    	;Activa bit 6 de Rxdreg si nºbits=7 y 1º bit LSB
		ENDIF
		ELSE
		bsf	Rxdreg,0    	;Activa bit 0 de Rxdreg si 1º el bit MSB
		ENDIF
				
		call	Delay_bit	;Espera entre bits
		decfsz	Cont,F		;Decrementa contador de nº de bits
		goto	RxD_next
		call	Delay_bit
		IF	Sbit == 2
		call	Delay_bit
		ENDIF			;Espera 1 o 2 bits de stop
				
		return
				
;**************************************************************************************
;TxD:	Rutina de transmisión. Trás el bit de inicio se transmite la palabra contenida
;en el registro transmisor Txdreg seguido de uno o dos bits de stop según la variable
;Sbit

TxD		
		IF	T_Nbit == 8
		movlw	8		;Transmisión de palabras de 8 bits
		ELSE
		movlw	7		;Transmisión de palabras de 7 bits
		ENDIF
		movwf	Cont
		
		IF	T_MODO == 1 	;Si se transmite 1º el LSB y la palabra es de
		ELSE			;7 bits, el registro transmisor se desplaza
		IF	T_Nbit == 8	;una posición a la izquierda para descartar
		ELSE			;el 8º bit
		rlf	Txdreg,F
		ENDIF
		ENDIF						
				
		bcf	Txd_pin		;Transmite el bit de inicio
		call	Delay_bit

TxD_next	bcf	STATUS,C
		IF	T_MODO == 1
		rrf	Txdreg,F	;Desplazamiento a dcha si 1º es el bit LSB
		ELSE
		rlf	Txdreg,F	;Desplazamiento a izda. si 1º es el bit MSB
		ENDIF
				
		btfsc	STATUS,C
		bsf	Txd_pin		;Si el carry es uno, se transmite un "1"
		btfss	STATUS,C
		bcf	Txd_pin		;Si el carry es cero se transmite un "0"
		call	Delay_bit
		decfsz	Cont,F		;Decrementa contador de bits
		goto	TxD_next
			
		bsf	Txd_pin		;Transmite un bit de stop
		call	Delay_bit
				
		IF	Sbit == 2
		bsf	Txd_pin		;Transmite segundo bit de stop si Sbit=2
		call	Delay_bit
		ENDIF
				
		return
				
;***************************************************************************************
;Delay_bit:	Rutina de temporización para los intervalos entre bit y bit


Delay_bit	clrwdt
		movlw	DELAY_H
		movwf	Dlycnt_h
Delay_bit_1	movlw	DELAY_L
		movwf	Dlycnt_l
Delay_bit_2	decfsz	Dlycnt_l,F
		goto	Delay_bit_2
		decfsz	Dlycnt_h,F
		goto	Delay_bit_1
		return
 
;***************************************************************************************
;Delay_ini:	Rutina de temprización para el bit de inicio en el modo de recepción. Esta
;temporización es de 1.5 con respecto a la del resto de bits. Así se consigue que el
;muestreo sea aproximadamente en el centro de cada bit recibido.

Delay_ini	clrwdt
		movlw	DELAY_START_H
		movwf	Dlycnt_h
Delay_ini_1	movlw	DELAY_START_L
		movwf	Dlycnt_l
Delay_ini_2	decfsz	Dlycnt_l,F
		goto	Delay_ini_2
		decfsz	Dlycnt_h,F
		goto	Delay_ini_1
		return

						
