
		LIST	P=16F877		
		INCLUDE	<P16f877.inc>	


		__config 3F79


sincbit		EQU	0x50		;contador envio de bits
Wdata		EQU	0x51		;variable de intercambio de datos
CMData		EQU	0x52		;variable de comandos
RXmsb		EQU	0x53		;registros de recepcion de datos
RXlsb		EQU	0x54
RH			EQU	0x55		;Porcentaje de Humedad Relativa

temp    	equ 0x68
Flags		equ	0x69

PDel0		EQU	0x21
PDel1		EQU	0x22
PDel2		EQU	0x23
BUFFER		EQU	0x24
INNER		EQU	0x25			;delay variable mS
OUTER		EQU	0x26			;delay variable mS
Digito		EQU	0x27
Digito2		EQU	0x28

ASCII_H		EQU	0x31
ASCII_M		EQU	0x32
ASCII_L		EQU	0x33

HEXADECIMAL	EQU	0x34


;----------------------------------------------------------------------------

		org 	0x00		;vector de inicio
		goto 	INICIO
		org 	0x05		;despues del vector de interrupcion

;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
;----------------------------------------------------------------------------

INICIO			bsf		STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				movlw	0x06		;Puerto A en modo digital
				movwf	ADCON1
				clrf	TRISA		;PortA como salida	
				clrf	TRISB		;PortB como salida	
				bcf		STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-		
				clrf	PORTA		;Limpia latches puerto
				clrf	PORTB		;Limpia latches puerto
				clrf	Wdata		
				clrf	RXmsb
				clrf	RXlsb

;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
START      		call    LCD_INI         ;Inicia LCD (CFG puertos...)
				movlw	b'00111000'
				call	LCD_REG
START_1    		movlw   b'00000001'     ;Borrar LCD y Home          
           		call    LCD_REG                                     
           		movlw   b'00000110'     ;                           
                call    LCD_REG                                     
                movlw	b'00001111'     ;LCD On, cursor Off,Parpadeo Off
                call    LCD_REG                                     
				call	tbl_hygro
				call 	sht11_Set8bits
;###############################################################################
bucle			call 	PDelay			;retardo aprox 1/2 segundo
				call	sht11_Humedad	;muestrea la medida RXmsb:RXlsb

;############################----MOSTRAR EN LCD----#############################
				movf	RXlsb,w			;muestra la humedad relativa por LCD		
				call 	Hex_Ascii
				movlw   0x89            ;Direccion caracter
        	    call    LCD_REG                  	
				movf	ASCII_H,W 		;sobreescribe el dato 
				xorlw   0x30	        ;Comprueba si ASCII_H es cero (hay o no hay centenas?)
	            btfss   STATUS,Z		
	            goto	nocero1
				movlw	0x20			;Si no hay centenas, se genera un espacio en blanco
                CALL    LCD_DATOS       ;Visualiza caracter
                goto	nocero2

nocero1			movf	ASCII_H,W		;====================================
				CALL    LCD_DATOS       ;Visualiza caracter         
                
nocero2			movf	ASCII_M,W		;====================================
				CALL    LCD_DATOS       ;Visualiza caracter         
                movf	ASCII_L,W		;====================================
				CALL    LCD_DATOS       ;Visualiza caracter  
				movlw	'%'
				CALL    LCD_DATOS       ;Visualiza caracter  
 
				clrf	PORTB
				goto	bucle	
		
;=====================================================================;
;===============  RUTINA CONVERSION HEXA A ASCII  ====================;
;=====================================================================;
	
Hex_Ascii		MOVWF	HEXADECIMAL
    	  		clrf    ASCII_H       	;Para BCD D'0'
    	  		clrf    ASCII_M    		;Para BCD D'0'
    	  		clrf    ASCII_L         ;Para BCD D'0'

Centenas   		movlw  	.100	        
    	  		subwf   HEXADECIMAL,W   
    	  		btfss	STATUS,C        ;HEXADECIMAL es menor que 100 ?
    	  		goto    Decenas         ;Si
    	  		movwf   HEXADECIMAL     ;Salva el resto
    	  		incf    ASCII_H,F       ;Incrementa el contador de centenas BCD
    	  		goto    Centenas        ;Vuelve por otros 100

Decenas 	  	movlw   .10          	
    	  		subwf   HEXADECIMAL,W   
    	  		btfss	STATUS,C        ;HEXADECIMAL es menor que 10?
    	  		goto    Unidades        ;Si
    	  		movwf   HEXADECIMAL     ;Salva el resto
    	  		incf    ASCII_M,F       ;Incrementa el contador de decenas BCD
    	  		goto    Decenas         ;Vuelve por otros 10

Unidades  		movf    HEXADECIMAL,W   ;El resto pertenece es de BCD
    	  		movwf   ASCII_L         
    	  		clrf    HEXADECIMAL     

Bcd_A_Ascii 	movlw 	H'30'           ;H'30' --> W
    	  		iorwf   ASCII_L,F       ;Convierte de BCD a ASCII
    	  		iorwf   ASCII_M,F       ;Convierte de BCD a ASCII

     	 		movf    ASCII_H,F       ;ASCII_H --> F
     	 		btfsc   STATUS,Z        ;ASCII_H es 0?
     	 		goto    Espacio         ;Si
     	 		movlw   H'30'           ;H'30' --> W
     	 		iorwf   ASCII_H,F       ;Convierte de BCD a ASCII
     	 		return                  

Espacio   		movlw   '0'            	
     	 		movwf   ASCII_H  		
     	 		return                  

;===========================================================================;
;============================ RUTINAS LCD 2x16 =============================;
;===========================================================================;

LCD_E   	        BSF     PORTA,2         ;Activa señal E
        	        NOP
        	        NOP
        	        NOP                     ;Espera 1uS
        	        BCF     PORTA,2         ;Desactiva señal E
        	        RETURN        
                              
LCD_BUSY    	    BSF     PORTA,1         ;Pone el LCD en modo lectura
            	    BSF     STATUS,RP0      ;Selecciona el Banco 1
            	    MOVLW   0xFF  
     	           	MOVWF   TRISB           ;Puerta B act£a de entrada
 	               	BCF     STATUS,RP0      ;Selecciona el Banco 0
   	   		        BSF     PORTA,2         ;Activa el LCD (Señal E)
   	             	NOP           
L_BUSY     		    BTFSC   PORTB,7         ;Chequea el bit BUSY
                	GOTO    L_BUSY          ;Est  a "1" (Ocupado)
                	BCF     PORTA,2         ;Desactiva el LCD (Se¤al E)
                	BSF     STATUS,RP0      ;Selecciona el Banco 1
                	CLRF    TRISB           ;Puerta B actua como salida
                	BCF     STATUS,RP0      ;Selecciona el Banco 0
                	BCF     PORTA,1         ;Pone el LCD en modo escritura
                	RETURN        
                              
LCD_REG         	BCF     PORTA,0         ;Desactiva RS (Modo instruccion)
                	MOVWF   PORTB           ;Saca el codigo de instruccion
                	CALL    LCD_BUSY        ;Espera a que se libere el LCD
                	GOTO    LCD_E           ;Genera pulso en señal E
                              
LCD_DATOS       	BCF     PORTA,0         ;Desactiva RS (Modo instrucci¢n)
                	MOVWF   PORTB           ;Valor ASCII a sacar por PORTB
                	CALL    LCD_BUSY        ;Espera a que se libere el LCD
                	BSF     PORTA,0         ;Activa RS (Modo dato)  
                	GOTO    LCD_E           ;Genera pulso en señal E
                              
LCD_INI         	MOVLW   b'00111000'
                	CALL    LCD_REG         ;Codigo de instruccion
                	CALL    DELAY_5MS       ;Temporiza 5 mS.
                	MOVLW   b'00111000'
                	CALL    LCD_REG         ;Codigo de instruccion
                	CALL    DELAY_5MS       ;Temporiza 5 mS.
                	MOVLW   b'00111000'
                	CALL    LCD_REG         ;Codigo de instruccion
                	CALL    DELAY_5MS       ;Temporiza 5 mS.
                	RETURN            
                              
;****************************************************************************                                                               
;DELAY_5MS genera una temporizacion de 5mS necesario para la secuencia de
;inicio del LCD                         
                                        
DELAY_5MS  			movlw   .6        	; 1 set number of repetitions (B)
        			movwf   PDel0     	; 1 |
PLoop1  			movlw   .207      	; 1 set number of repetitions (A)
		       	 	movwf   PDel1     	; 1 |
PLoop2 				nop              	; 1 clear watchdog
        			decfsz  PDel1, 1  	; 1 + (1) is the time over? (A)
        			goto    PLoop2    	; 2 no, loop
        			decfsz  PDel0,  1 	; 1 + (1) is the time over? (B)
        			goto    PLoop1    	; 2 no, loop
PDelL1  			goto	PDelL2      	; 2 cycles delay
PDelL2  			nop              	; 1 cycle delay
		        	return              	; 2+2 Done
;###########################################################################


PDelay  			movlw   .90      	; 1 set number of repetitions (C)  ;.167
        			movwf   PDel0     	; 1 |
PLoop0s  			movlw   .41       	; 1 set number of repetitions (B)
        			movwf   PDel1     	; 1 |
PLoop1s  			movlw   .72      	; 1 set number of repetitions (A)
        			movwf   PDel2     	; 1 |
PLoop2s  			nop	              	; 1 clear watchdog
        			decfsz  PDel2,1  	; 1 + (1) is the time over? (A)
        			goto    PLoop2s   	; 2 no, loop
        			decfsz  PDel1,1 	; 1 + (1) is the time over? (B)
        			goto    PLoop1s   	; 2 no, loop
        			decfsz  PDel0,1 	; 1 + (1) is the time over? (C)
        			goto    PLoop0s    	; 2 no, loop
PDelL1s  			goto 	PDelL2s     ; 2 cycles delay
PDelL2s  			nop              	; 1 cycle delay
        			return              ; 2+2 Done
;-------------------------------------------------------------
;//////////////////RUTINAS SENSOR SHT11/////////////////////////////;

sht11_Humedad										;LECTURA HUMEDAD 2 bytes
				call 	SHT11_start	;	Inicio de transmision
				movlw	b'00000101'
				call	SHT11_CMD	;	Envio: Lectura de humedad
				call	waitACK		;	espera que llegue ACK desde el sensor
				call	adqtime		;	espera que pase el tiempo de adquisicion
				call	readMSB		;	lee el byte alto
				call	setACK
				call	readLSB		;	lee el byte bajo
				call	setNACK
				call	CalcRH		;	Calcula %RH y ajusta linealidad, vuelve con el valor en RH
				return			
	
;------------------------------------------------------------------------------------------------------------------------------------
sht11_Tempera										;LECTURA TEMPERATURA 2 bytes
				call 	SHT11_start	;	Inicio de transmision
				movlw	b'00000011'
				call	SHT11_CMD	;	Envio: Lectura de Temperatura
				call	waitACK		;	espera que llegue ACK desde el sensor
				call	adqtime		;	espera que pase el tiempo de adquisicion
				call	readMSB		;	lee el byte alto
				call	waitACK
				call	setACK
				call	readLSB		;	lee el byte bajo
				call	setNACK
				call	CalcRH		;	Calcula %RH y ajusta linealidad, vuelve con el valor en RH
				return		
;------------------------------------------------------------------------------------------------------------------------------------		
sht11_Set8bits										;configura el sensor para trabajar en modo 8 bits
				call 	SHT11_start	;	Inicio de transmision
				movlw	b'00000110'	
				call	SHT11_CMD	;	Envio: Escritura de registro interno
				call	waitACK		;	espera que llegue ACK desde el sensor
				bcf		RXmsb,0		;	pone un 0 en el bit 0 de status... (12 bit RH, 14 bit °T)
				movf	RXmsb,W		;	y carga el stats modificado del sensor
				call	SHT11_CMD	;	Envio: modificacion de status
				call	waitACK		;	espera que llegue ACK desde el sensor					

				return
		
;-------------------------------------------------------------------------------------------------------------------------------------
SHT11_start										;transmision start
				bsf		STATUS,RP0	;	banco 1
				bcf		STATUS,RP1
				bcf		TRISB,0		;	puertos como salida		;////////////// AJUSTAR ESTOS PARAMETROS \\\\\\\\\\\\\\\\
				bcf		TRISB,1
				bcf		STATUS,RP0	;	banco 0
				bsf		PORTB,0		;	DATA a 1 (por defecto)
				nop					;	espera un poco
				nop
				bsf		PORTB,1		;	Se aCLK
				bcf		PORTB,0		;	DATA	(pulso bajo)
				bcf		PORTB,1		;	Se da un pulso que pasa de alto a bajo y luego nuevamente a alto en el bit CLK 
				bsf		PORTB,1		;	mientras DATA se encuentra en estado bajo.
				bsf		PORTB,0		;	DATA (por defecto alto)
				bcf		PORTB,1		;	
				return

;-------------------------------------------------------------------------------------------------------------------------------------
SHT11_CMD	
				movwf	CMData		;	guarda el comando en variable
				clrf	sincbit
				bcf		STATUS,C	;	borra carry
				bsf		STATUS,RP0	;	banco 1
				bcf		TRISB,0		;	pone DATA port,0 como salida
				bcf		STATUS,RP0	;	banco 0
		
cont_send		rlf		CMData,F	;	rota a la izquierda, bit alto en carry
;envio de datos segun el protocolo del sht11
send_data		btfsc	STATUS,C	;	comprueba si es 1 o 0
				goto	uno			;
cero			bcf		PORTB,1		;	SCK  falling edge -_
				bcf		PORTB,0		;	DATA change
				bsf		PORTB,1		;	SCK  rising edge  _-
				goto	sht11_compTX	;	salta
uno				bcf		PORTB,1		;	SCK  falling edge -_
				bsf		PORTB,0		;	DATA change
				bsf		PORTB,1		;	SCK  rising edge  _-
;Comprobacion para 8 rotaciones, una por bit del comando.
sht11_compTX    movlw 	.7			;	comprobacion 8 bits
                subwf  	sincbit,W   ;	Compara 
                btfsc   STATUS,Z   	;	Es el ultimo?             
                return				;	Si, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                incf    sincbit,f   ;	Incrementa numero de sincbit
                goto    cont_send	;	Vuelve a escribir

;-------------------------------------------------------------------------------------------------------------------------------------
waitACK											;espera el ACK del sensor
				bsf		STATUS,RP0	;	banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				bsf		TRISB,0		;	pone DATA port,0 como entrada
				bcf		STATUS,RP0	;	banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-	
				nop
				nop
				nop
				nop		
ACKrx			bcf		PORTB,1		;	SCK  falling edge
				nop
				nop					;	5uS de retardo
				nop
				nop
				nop
				bsf		PORTB,1		;	SCK  rising edge
				btfsc	PORTB,0		;	comprueba data
				goto	ACKrx		;	NO, bucle
				bcf		PORTB,1		;	SCK  falling edge estado bajo por defecto
				return


;-------------------------------------------------------------------------------------------------------------------------------------
adqtime			btfsc	PORTB,0		;	comprueba data
				goto	adqtime		;	NO, bucle
				return

;-------------------------------------------------------------------------------------------------------------------------------------
readMSB			
				clrf	RXmsb		;	limpia registro
				bsf		RXmsb,0		;	pone un 1 que indicara en carry el final
leemsb			bcf		PORTB,1		;	SCK  falling edge
				bsf		PORTB,1		;	SCK  rising edge
				btfss	PORTB,0		;	lee data
				goto	es_ceromsb
es_unomsb		rlf		RXmsb,f		;	rota a la izquierda
				bsf		RXmsb,0		;	pone un 1  en el bit 0
				btfss	STATUS,C	;	salio la marca por carry?
				goto	leemsb		;	continua y captura el siguiente bit
				return
es_ceromsb		rlf		RXmsb,f		;	rota a la izquierda
				bcf		RXmsb,0		;	pone un 0  en el bit 0
				btfss	STATUS,C	;	salio la marca por carry?
				goto	leemsb		;	continua y captura el siguiente bit
				return	

;-------------------------------------------------------------------------------------------------------------------------------------
readLSB			
				clrf	RXlsb		;	limpia registro
				bsf		RXlsb,0		;	pone un 1 que indicara en carry el final
leelsb			bcf		PORTB,1		;	SCK  falling edge
				bsf		PORTB,1		;	SCK  rising edge
				btfss	PORTB,0		;	lee data
				goto	es_cerolsb
es_unolsb		rlf		RXlsb,f		;	rota a la izquierda
				bsf		RXlsb,0		;	pone un 1  en el bit 0
				btfss	STATUS,C	;	salio la marca por carry?
				goto	leelsb		;	continua y captura el siguiente bit
				return
es_cerolsb		rlf		RXlsb,f		;	rota a la izquierda
				bcf		RXlsb,0		;	pone un 0  en el bit 0
				btfss	STATUS,C	;	salio la marca por carry?
				goto	leelsb		;	continua y captura el siguiente bit
				return		


;-------------------------------------------------------------------------------------------------------------------------------------
setACK			
				bsf		STATUS,RP0	;	banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				bcf		TRISB,0		;	pone DATA port,0 como salida
				bcf		STATUS,RP0	;	banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-

				bcf		PORTB,1		;	SCK  falling edge		
				bcf		PORTB,0
				bsf		PORTB,1		;	DATA change nivel logico 0	bcf
				bcf		PORTB,1		;	SCK rising edge
				bsf		STATUS,RP0	;	banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				bsf		TRISB,0		;	pone DATA port,0 como entrada
				bcf		STATUS,RP0	;	banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				return

;-------------------------------------------------------------------------------------------------------------------------------------
setNACK			
				bsf		STATUS,RP0	;	banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				bcf		TRISB,0		;	pone DATA port,0 como salida
				bcf		STATUS,RP0	;	banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-	
				bcf		PORTB,1		;	SCK  falling edge
				bsf		PORTB,0		;	DATA change nivel logico 0
				bsf		PORTB,1		;	SCK  rising edge
				nop
				bcf		PORTB,1		;	baja clk		
				bsf		STATUS,RP0	;	banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				bsf		TRISB,0		;	pone DATA port,0 como entrada
				bcf		STATUS,RP0	;	banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
				return

;-------------------------------------------------------------------------------------------------------------------------------------
CalcRH										;RH% calculos de linealidad. 
;-------------------------------------------------------------------------------------------------------------------------------------

tbl_hygro		movlw	0x80
				call	LCD_REG
				movlw	'H'
				call	LCD_DATOS
				movlw	'u'
				call	LCD_DATOS
				movlw	'm'
				call	LCD_DATOS
				movlw	'e'
				call	LCD_DATOS
				movlw	'd'
				call	LCD_DATOS
				movlw	'a'
				call	LCD_DATOS
				movlw	'd'
				call	LCD_DATOS
				movlw	':'
				call	LCD_DATOS
				return

	END
