;
;					EJEMPLO 34
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo para MicroPIC Trainer y Micro'PIC Trainer Plus
;
;El módulo MSSP. Modo I2C Master. 
;
;El módulo MSSP de los dispositivos PIC16F87X incorpora por hardware el interface I2C tanto
;en el modo Master como en el modo Slave. Las líneas RC3/SCL y RC4/SDA actúan como señales
;de reloj y datos del bus I2C respectivamente.
;
;El dispositivo I2C SAA1064. Controlador de displays de 7 segmentos
;
;Se trata de visualizar sobre los 4 displays 7 segmentos de la tarjeta Micro'PIC Trainer PLUS
;el contenido de las variables BCD_1 y BCD_2

		List	p=16F873	;Tipo de procesador
		include	"P16F873.INC"	;Definiciones de registros internos

BCD_0		equ	0x20
BCD_1		equ	0x21
BCD_2		equ	0x22		;Variables BCD

		org	0x00		;Vector de Reset
		goto	Inicio

		org	0x05		;Salva el vector de interrupción

;***************************************************************************************
;BCD_7seg: Rutina de conversión de BCD (0-9) a 7 segmentos. El acumulador W contiene,
;durante la llamada, el código BCD y, al retornar, el correspondiente a 7 segmentos
;
BCD_7seg:	andlw	b'00001111'
		addwf	PCL,F		;Desplazamiento sobre la tabla
		retlw	b'00111111'	;0
		retlw	b'00000110'	;1
		retlw	b'01011011'	;2
		retlw	b'01001111'	;3
		retlw	b'01100110'	;4
		retlw	b'01101101'	;5
		retlw	b'01111101'	;6
		retlw	b'00000111'	;7
		retlw	b'01111111'	;8
		retlw	b'01100111'	;9

;********************************************************************************************
;Visualiza: Recoge el valor actual de las variables BCD_1 y BCD_2, desempaqueta en dígitos
;individuales, convierte a 7 segmentos y visualiza sobre los cuatros displays controlados por
;el dispositivo I2C SAA1064

Visualiza	call	Send_Start	;Envía secuencia de inicio
		movlw	b'01110110'
		call	Send_Byte	;Dirección del dispositivo SAA1064 en la PLUS
		movlw	.0
		call	Send_Byte	;Envía byte de instrucción
		movlw	b'01000111'
		call	Send_Byte	;Envía byte de control
		swapf	BCD_1,W
		andlw	0x0f		;Coge nibble de más peso de BCD_1
		call	BCD_7seg	;Convierte a 7 segmentos
		call	Send_Byte	;Visualiza sobre el dígito D1
		movlw	0x0f
		andwf	BCD_1,W		;Coge nibble de menos peso de BCD_1
		call	BCD_7seg	;Convierte a 7 segmentos
		call	Send_Byte	;Visualiza sobre el dígito D2
		swapf	BCD_2,W
		andlw	0x0f		;Coge nibble de más peso de BCD_2
		call	BCD_7seg	;Convierte a 7 segmentos
		call	Send_Byte	;Visualiza sobre el dígito D3
		movlw	0x0f
		andwf	BCD_2,W		;Coge nibble de menos peso de BCD_2
		call	BCD_7seg	;Convierte a 7 segmentos
		call	Send_Byte	;Visualiza sobre el dígito D4
		call	Send_Stop	;Envía secuencia de stop
		return
						
;*******************************************************************************************
;Send_Start: Envía la condición de inicio

Send_Start	bcf	PIR1,SSPIF	;Restaura el flag del módulo MSSP
		bsf	STATUS,RP0	;Seleciona página 1
		bsf	SSPCON2,SEN	;Activa secuencia de inicio
		bcf	STATUS,RP0
Start_Wait	btfss	PIR1,SSPIF	;Fin de secuencia de inicio ??
		goto	Start_Wait	;No, esperar		
		return

;*******************************************************************************************
;Send_Stop: Envía la secuencia de stop

Send_Stop	bcf	PIR1,SSPIF	;Restaura el flag del módulo MSSP
		bsf	STATUS,RP0	;Seleciona página 1
		bsf	SSPCON2,PEN	;Activa secuencia de stop
		bcf	STATUS,RP0
Stop_Wait	btfss	PIR1,SSPIF	;Fin de secuencia de Stop ??
		goto	Stop_Wait	;No, esperar
		return

;*******************************************************************************************
;Send_Byte: Transmite el byte del W vía I2C. La rutina finaliza cuando se recibe /ACK

Send_Byte	bcf	PIR1,SSPIF	;Restaura el flag del módulo MSSP
		movwf	SSPBUF		;Byte a transmitir pasa al buffer de salida
Send_Byte_Wait	btfss	PIR1,SSPIF	;Recibido el bit /ACK ??
		goto	Send_Byte_Wait	;No, esperar
		return

;*******************************************************************************************
;Read_Byte: Lee un byte procedente del dispositivo I2C selecionado y lo devuelve en W
;Seguidamente se genera y transmite el bit /ACK

Read_Byte	bcf	PIR1,SSPIF	;Restaura el flag del módulo MSSP
		bsf	STATUS,RP0	;Selecciona página 1
		bsf	SSPCON2,RCEN	;Activa el modo receptor
		bcf	STATUS,RP0	;Selecciona página 0
Read_Wait	btfss	PIR1,SSPIF	;Recibidos los 8 bits ??
		goto	Read_Wait	;No, esperar

		bcf	PIR1,SSPIF	;Restaura el flag del módulo MSSP
		bsf	STATUS,RP0	;Selecciona página 1
		bcf	SSPCON2,ACKDT	;Pone bit ACK a "0"
		bsf	SSPCON2,ACKEN	;Aciva la secuencia de generación del bit ACK
		bcf	STATUS,RP0	;Selecciona página 0
ACK_Wait	btfss	PIR1,SSPIF	;Secuencia ACK finalizada ??
		goto	ACK_Wait	;No, esperar
		movf	SSPBUF,W	;Lee el byte recibido
		return

;*******************************************************************************************
;Programa principal

Inicio	     	clrf	PORTC		
		bsf	STATUS,RP0	;Selecciona banco 1
		movlw	b'11111111'
		movwf	TRISC		;RC3/SCL y RC4/SDA entradas
		movlw	b'11001111'
		movwf	OPTION_REG	;Preescaler de 128 asociado al WDT
		movlw	b'10000000'
		movwf	SSPSTAT		;Velocidad estándar con niveles I2C
		movlw	.9
		movwf	SSPADD		;Velocidad del bus I2C 100KHz
		bcf	STATUS,RP0	;Selecciona banco 0

;Módulo MSSP en el modo Master I2C

		movlw	b'00101000'
		movwf	SSPCON		;Módulo MSSP en On

		movlw	High 0x9356
		movwf	BCD_1
		movlw	Low 0x9356
		movwf	BCD_2		;Valor a visualizar (p.e. 9356)
		call	Visualiza	;Visualiza

Loop		clrwdt
		goto	Loop

		end			;Fin del programa fuente
