;**************************** Librería "DS18B20.INC" ***********************************
;
;	===================================================================
;	  Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;	  E. Palacios, F. Remiro y L. López. 		www.pic16f84a.com
; 	  Editorial Ra-Ma.  www.ra-ma.es
;	===================================================================
;
; Estas subrutinas permiten realizar las tareas de manejo del sensor de temperatura DS18B20.
; Este sensor transmite la información vía serie a través de un 1-Wire Bus.
;
; ZONA DE DATOS **********************************************************************

	CBLOCK
	DS18B20_Temperatura						; Primer byte leído del termómetro DS18B20.
	DS18B20_TemperaturaH					; Segundo byte leído del termómetro DS18B20.
	DS18B20_TemperaturaSigno				; Indica el signo de la temperatura.
	DS18B20_TemperaturaDecimal				; Parte decimal de la temperatura medida.
	ENDC

DS18B20_Skip_ROM_Command			EQU	0xCC	; Comandos del DS18B20.
DS18B20_Read_Scratchpad_Command	EQU	0xBE
DS18B20_Convert_T_Command		EQU	0x44
;
; Subrutina "DS18B20_RedondeaDecimal" ----------------------------------------------------
;
; Esta subrutina redondea el valor del contenido del registro de trabajo W al valor más cercano
; con un decimal indicado en una tabla.
;
DS18B20_RedondeoDecimal
	addwf	PCL,F	
	retlw	d'0'	; (DS18B20_Decimal)=b'0000'. Mide 0,0000ºC. Redondeado a 0,0ºC.
	retlw	d'1'	; (DS18B20_Decimal)=b'0001'. Mide 0,0625ºC. Redondeado a 0,1ºC.
	retlw	d'1'	; (DS18B20_Decimal)=b'0010'. Mide 0,1250ºC. Redondeado a 0,1ºC.
	retlw	d'2'	; (DS18B20_Decimal)=b'0011'. Mide 0,1875ºC. Redondeado a 0,2ºC.
	retlw	d'3'	; (DS18B20_Decimal)=b'0100'. Mide 0,2500ºC. Redondeado a 0,3ºC.
	retlw	d'3'	; (DS18B20_Decimal)=b'0101'. Mide 0,3125ºC. Redondeado a 0,3ºC.	
	retlw	d'4'	; (DS18B20_Decimal)=b'0110'. Mide 0,3750ºC. Redondeado a 0,4ºC.
	retlw	d'4'	; (DS18B20_Decimal)=b'0111'. Mide 0,4375ºC. Redondeado a 0,4ºC.
	retlw	d'5'	; (DS18B20_Decimal)=b'1000'. Mide 0,5000ºC. Redondeado a 0,5ºC.
	retlw	d'6'	; (DS18B20_Decimal)=b'1001'. Mide 0,5625ºC. Redondeado a 0,6ºC.
	retlw	d'6'	; (DS18B20_Decimal)=b'1010'. Mide 0,6250ºC. Redondeado a 0,6ºC.
	retlw	d'7'	; (DS18B20_Decimal)=b'1011'. Mide 0,6875ºC. Redondeado a 0,7ºC.	
	retlw	d'8'	; (DS18B20_Decimal)=b'1100'. Mide 0,7500ºC. Redondeado a 0,8ºC.
	retlw	d'8'	; (DS18B20_Decimal)=b'1101'. Mide 0,8125ºC. Redondeado a 0,8ºC.
	retlw	d'9'	; (DS18B20_Decimal)=b'1110'. Mide 0,8750ºC. Redondeado a 0,9ºC.
	retlw	d'9'	; (DS18B20_Decimal)=b'1111'. Mide 0,9375ºC. Redondeado a 0,9ºC.
DS18B20_FinTablaRedondeo

	IF (DS18B20_FinTablaRedondeo > 0xFF)
		ERROR	"¡CUIDADO!: La tabla ha superado el tamaño de la página de los"
		MESSG	"primeros 256 bytes de memoria ROM. NO funcionará correctamente."
	ENDIF

; Subrutina "DS18B20_Inicializa" ---------------------------------------------------------
;
; Inicializa el DS18B20 para que comience la conversión de temperatura.
;
DS18B20_Inicializa
	call	Bus1Linea_Reset				; Primero los pulsos de Reset y Presence.
	movlw	DS18B20_Skip_ROM_Command 	; Salta los comandos de ROM ya que hay
	call	Bus1Linea_EscribeByte		; conectado un único dispositivo al bus.
	movlw	DS18B20_Convert_T_Command	; Para que comience la conversión de temperatura.
	call	Bus1Linea_EscribeByte
	return

; Subrutina "DS18B20_LeeTemperatura" -----------------------------------------------------
;
; El DS18B20 lee la temperatura en un formato ejemplarizado como sigue:
;
; +125,0 ºC	  00000111 11010000
; + 85,0 ºC   00000101 01010000
; + 25,5 ºC	  00000001 10011000
; + 25,0625ºC 00000001 10010001
; + 25,0 ºC	  00000001 10010000
; + 10,125ºC  00000000 10100010
; +  0,5 ºC	  00000000 00001000
; +  0,0 ºC	  00000000 00000000
; -  0,5 ºC	  11111111 11111000
; - 10,125ºC  11111111 01011110
; - 25,0 ºC	  11111110 01110000
; - 25,0625ºC 11111110 01101111
; - 25,5 ºC	  11111110 01101000
; - 55,0 ºC   11111100 10010000
; - 85,0 ºC   11111010 10110000
;
; Se observa que:
;     -	El formato es de dos bytes. El primer bit es el de signo.
;     -	Las temperaturas positivas comienzan con 1 bit a cero:  "0xxxxxxx xxxxxxxx".
;     -	Las temperaturas negativas comienzan con 1 bit a a uno: "1xxxxxxx xxxxxxxx".
;     -	El nible bajo del byte bajo es la parte decimal.
;     -	La parte entera la conforman el nible bajo del byte alto y el nible alto del byte bajo.
;		Por ejemplo: +25ºC = xxxx0001 1001xxxx = 25 en decimal.
;     -	Las temperaturas negativas vienen dadas en complemento a 2. Por tanto para obtener
;		su valor absoluto habrá que negarlas.
;
; Esta subrutina lee la temperatura proporcionando tres datos: 
;
; Salida:
;	- En el registro DS18B20_Temperatura, el valor de la temperatura en valor absoluto.
;	- En el registro DS18B20_TemperaturaDecimal, la parte decimal del valor de la temperatura.
;	- En (DS18B20_TemperaturaSigno)=b'11111111' si la temperatura es negativa y
;	  (DS18B20_TemperaturaSigno)=b'00000000' si es positiva.
;
DS18B20_LeeTemperatura
	call	Bus1Linea_Reset				; Primero los pulsos de "Reset" y "Presence".
	movlw	DS18B20_Skip_ROM_Command 	; Salta los comandos de ROM ya que hay
	call	Bus1Linea_EscribeByte		; conectado un único dispositivo al bus.
	movlw	DS18B20_Read_Scratchpad_Command ; Va a leer la primera posición de memoria,
	call	Bus1Linea_EscribeByte		; donde se localiza el valor de la temperatura.
	call	Bus1Linea_LeeByte			; Lee la temperatura en 
	movwf	DS18B20_Temperatura			; complemento a 2.
	call	Bus1Linea_LeeByte			; Ahora lee el segundo byte
	movwf	DS18B20_TemperaturaH		; de la temperatura.
	call	Bus1Linea_Reset				; Y para terminar, resetea el dispositivo.
;
; Ahora deduce si la temperatura es positiva o negativa y halla su valor absoluto.
;
	btfss	DS18B20_TemperaturaH,7		; Si cualquier bit es "1": temperatura negativa.
	goto	DS18B20_FinLeeTemperatura	; La temperatura es positiva y salta.
DS18B20_TemperaturaNegativa
	comf	DS18B20_TemperaturaH,F		; Obtiene el valor absoluto de la temperatura.
	comf	DS18B20_Temperatura,F
	movlw	.1
	addwf	DS18B20_Temperatura,F
	btfsc	STATUS,C
	incf	DS18B20_TemperaturaH,F
	movlw	0xFF
	movwf	DS18B20_TemperaturaSigno
DS18B20_FinLeeTemperatura
	movf	DS18B20_Temperatura,W		; Se queda con la parte decimal que es el nible
	andlw	b'00001111'					; bajo del primer byte.
	call	DS18B20_RedondeoDecimal		; Obtiene el valor redondeado.
	movwf	DS18B20_TemperaturaDecimal	; La parte decimal.

; Ahora va a obtener el valor de la temperatura en un solo byte.

	movlw	b'11110000'					; Se queda con el nible alto del primer byte leído.
	andwf	DS18B20_Temperatura,F		;
	movlw	b'00001111'					; Ahora el nible bajo del segundo byte leído.
	andwf	DS18B20_TemperaturaH,W
	iorwf	DS18B20_Temperatura,F		; Una OR con los dos nibles.
	swapf	DS18B20_Temperatura,F		; Se intercambian los nibles.
	movf	DS18B20_Temperatura,W		; En (W) la parte entera del valor absoluto de la
	return								; temperatura.
	
;	===================================================================
;	  Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;	  E. Palacios, F. Remiro y L. López. 		www.pic16f84a.com
; 	  Editorial Ra-Ma.  www.ra-ma.es
;	===================================================================
