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.
1 2 3 |
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”.
1 2 3 4 |
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:
1 2 3 4 |
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ì:
1 2 3 4 5 6 7 8 |
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:
1 2 3 4 5 6 7 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
;__________________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é.