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]](https://insight.stefanopaladini.net/wp-content/uploads/2014/07/display.jpg)
;__________________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 Febbraio 2020 at 10:40
Hai anche una versione del codice in C?
2 Febbraio 2020 at 13:53
Mi spiace, quando ho scritto questo codice, specialmente per il 16f84, il C non si usava granché.