InSight

Scienza e Tecnologia nella vita di tutti i giorni

Sonda di temperatura DS18B20

Il codice per PIC 16F84A – Routine principale

Adesso che abbiamo le routines “di servizio” possiamo d analizzare la routine principale denominata “Acquisition”. Come abbiamo già detto, la prima cosa da fare nel dialogo con la sonda è chiamare la inizializza_ds1820 che si occupa degli impulsi di reset e presence.

Acquisition
		call	inizializza_ds1820	; inizializzazione e riconoscimento del DS1820
		call	delay_600us

Dopo il comando di inizializzazione bisogna inviare il comando ROM che riguarda l’identificazione della sonda attraverso il codice a 64 bit. Nel nostro caso inviamo il comando skip ROM, che corrisponde al valore esadecimale 0xCC, in quanto, avendo una sola sonda, l’identificazione è superflua.
Per far questo ci appoggiamo alla variabile ds1820, menzionata in precedenza, che passiamo alla routine scrivi_ds1820 che si occupa della trasmissione vera e propria.
Il comando skip ROM dice alla sonda di “saltare” l’invio del codice univoco da 64 bit.
Quando la sonda riceve questo comando sa che subito dopo deve attendersi un comando diretto che riguarda le sue funzioni di “sonda”.

movlw	0xCC
	movwf	ds1820
	call	scrivi_ds1820		; salta la ROM
	call	delay_600us

Queste istruzioni eseguono le seguenti operazioni:

  • mettere il valore 0xCC nell’accumulatore
  • mettere il valore dell’accumulatore nel registro ds1820
  • chiama la routine scrivi ds1820
  • aspetta 600 microsecondi

Avendo già analizzato la scrvi_ds1820, le operazioni di cui sopra sono relativamente banali.

Per inciso la sonda ha anche una configuration word che può essere programmata e una memoria in cui memorizzare un valore di temperatura in base al quale la sonda può fare da allarme settando un flag quando la temperatura supera tale valore.
In questo caso non facciamo uso di nessuna di queste funzioni ma, una volta capito come funziona il dialogo, è sufficiente cambiare le parole di comando e riutilizzare le stesse routines.

Dopo il comando skip-rom (CCH) la sonda si aspetta un comando riguardante o le sue funzioni di sonda o delle operazioni di memoria. Quindi dopo il comando di ROM mandiamo un comando di funzione:

movlw	0x44
	movwf	ds1820
	call	scrivi_ds1820		; comando 0x44: converti temperatura
	call	delay_1s		;tempo necessario per la conversione 750ms -> attesa 1s

In questo caso il comando è il 0x44=converti temperatura.
Dopo questo comando la sonda rimane inattiva per il tempo necessario a leggere la temperatura e convertirne il valore in binario. Il tempo necessario dipende dalla risoluzione impostata.
Per default la sonda è impostata alla risoluzione massima di 12bit e in questo caso il tempo richiesto è di 750ms. Nel codice è impostato un valore approssimato per eccesso pari a 1s.

Dopo l’esecuzione del comando converti temperatura, la sonda ha completato il ciclo di tre passi illustrato precedentemente. Per eseguire un nuovo comando, la routine principale dovrà nuovamente eseguire l’operazione di reset e skip ROM.

Quello che dobbiamo fare adesso è leggere la scratchpad cioè la memoria in cui viene memorizzato l’ultimo valore di temperatura convertito.
Il codice si presenta così:

	call	inizializza_ds1820
	call	delay_600us
	movlw	0xCC
	movwf	ds1820
	call	scrivi_ds1820		; salta la ROM
	movlw	0xBE
	movwf	ds1820
	call	scrivi_ds1820		; comando 0xBE: leggi la Scratchpad

Si tratta delle routines viste precedentemente; come unica differenza vi è appunto il comando leggi scratchpad (0xBE) il quale dice alla sonda che subito dopo dovrà inviarci il dato di temperatura.
Quindi immediatamente dopo aver inviato il comando 0xBE facciamo due chiamate consecutive alla leggi_ds1820 vista precedentemente:

		call	leggi_ds1820
		movf	ds1820, w
		movwf	temp2			; Temperatura LSB  
		call	leggi_ds1820
		movf	ds1820, w
		movwf	temp1			; Temperatura MSB
		return

Questo perchè il dato di temperatura è contenuto in due byte e alla fine di queste istruzioni li troveremo salvati nelle due variabili temp1 e temp2.

Riaggregando le routines che abbiamo analizzato singolarmente abbiamo di seguito il codice completo della Acquisition che può essere chiamata all’interno di un programma più ampio come per esempio un termometro digitale che visualizzi il valore di temperatura su un display alfanumerico come quello mostrato in figura.

[cml_media_alt id='2053']display[/cml_media_alt]

;__________________Data acquisition______________________
Acquisition
		call	inizializza_ds1820	; inizializzazione e riconoscimento del DS1820 
		call	delay_600us

		movlw	0xCC
		movwf	ds1820
		call	scrivi_ds1820		; salta la ROM
		call	delay_600us

		movlw	0x44
		movwf	ds1820
		call	scrivi_ds1820		; comando 0x44: converti temperatura

		call	delay_1s		;tempo necessario per la conversione 750ms -> attesa 1s

		call	inizializza_ds1820
		call	delay_600us

		movlw	0xCC
		movwf	ds1820
		call	scrivi_ds1820		; salta la ROM

		movlw	0xBE
		movwf	ds1820
		call	scrivi_ds1820		; comando 0xBE: leggi la Scratchpad

		call	leggi_ds1820
		movf	ds1820, w
		movwf	temp2			; Temperatura LSB  
		call	leggi_ds1820
		movf	ds1820, w
		movwf	temp1			; Temperatura MSB
		return

inizializza_ds1820
		bcf		PORTA, 4
		call	delay_600us			; 600 us se e' zero -> resetta
		bsf		PORTA, 4
		call	delay_80us			; Aspetta 80 us 
		bcf		errore,0
		btfsc	PORTA, 3
		bsf		errore,0		;La sonda non ha risposto -> errore
		return

scrivi_ds1820
		movlw	0x08
		movwf	KEY

scrivi_ds1820_loop
		rrf		ds1820, F		; sposta verso destra
		nop
		btfss	STATUS, C
		goto	$+3
		call	scrivi_uno
		goto	$+2
		call	scrivi_zero

		decfsz	KEY, f
		goto	scrivi_ds1820_loop		; continua fino a che sono stati inviati 8 bit
		return

scrivi_uno
		bcf	PORTA, 4
		call	delay_7us		; Aspetta 7 us 
		bsf	PORTA,4
		call	delay_80us		; Aspetta 80 us 
		return

scrivi_zero
		bcf	PORTA,4
		call	delay_80us		; Aspetta 80 us 
		bsf	PORTA,4
		return

leggi_ds1820
		clrf	ds1820
		bcf	STATUS, C
		movlw	0x08
		movwf	KEY

leggi_ds1820_loop
		bcf	PORTA, 4		; basso -> 0
		nop
		nop
		bsf	PORTA, 4		; se e' alto non sara'_ trasmesso
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		bsf	STATUS, C
		btfss	PORTA,3			; campionamento del bus
		bcf	STATUS,C
		rrf	ds1820,f		; sposta verso destra
		call	delay_80us		; Aspetta 80 us 
		decfsz	KEY, f
		goto	leggi_ds1820_loop	; Aspetta fino a che sono stati inviati 8 bit
		return
;_______________________________________________________________________________________________
;--------routines di ritardo per il dialogo con DS18B20------------------

delay_600us           movlw 0xC6		; Aspetta 600 us
                      movwf d1
delay_600us_loop      decfsz d1, f
                      goto delay_600us_loop
                      nop
                      return

delay_50us            movlw 0x0F		; Aspetta 50 us
                      movwf d1
delay_50us_loop       decfsz d1, f
                      goto delay_50us_loop
                      return

delay_30us            movlw 30		; Aspetta 30 us
                      movwf d1
delay_30us_loop       decfsz d1, f
                      goto delay_30us_loop
                      return

delay_15ms            movlw 182		; Aspetta 15 ms
                      movwf d1
                      movlw 12
                      movwf d2
delay_15ms_loop       decfsz d1, f
                      goto $+2
                      decfsz d2, f
                      goto delay_15ms_loop
                      goto $+1
                      nop
                      return

delay_7us             goto $+1		; Aspetta 7 us
                      nop
                      nop
                      return

delay_80us            movlw 0x19		; Aspetta 80 us
                      movwf d1
delay_80us_loop       decfsz d1, f
                      goto delay_80us_loop
                      return

delay_1s              movlw 0x07		; Aspetta 1 s
                      movwf d1
                      movlw 0x2F
                      movwf d2
                      movlw 0x03
                      movwf d3
delay_1s_loop         decfsz d1, f
                      goto $+2
                      decfsz d2, f
                      goto $+2
                      decfsz d3, f
                      goto delay_1s_loop
                      goto $+1
                      goto $+1
                      goto $+1
                      return

Nota: I diagrammi e i grafici presenti i questo articolo sono tratti dal datasheet ufficiale
del componente.

2 commenti

  1. Diego Bincoletto

    2 Febbraio 2020 at 10:40

    Hai anche una versione del codice in C?

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

© 2026 InSight

Based upon a Anders Noren themeSu ↑