'' DS1820 One wire routines. Copyright Brad Campbell 2008 '' Rev 1 - All delays calculated for clkfreq independence '' - Modified _P_ version for Parasitic Power '' - Split RTC into separate file '' - Consolidated lots of delay calculations '' Rev 2 - Re-wrote completely in Spin (takes about 800mSec to get temp in one wire mode) '' - Polled conversion now. After Start_Conversion poll Get_Temperature regularly '' - In addition to raw data, return extended temperature * 100 (2 dec place precision) '' - Full data CRC checking '' - Treat a return of 85.0C (DS18S20 conversion error) same as CRC error and ignore '' - Determine sensors power source and adjust for Parastite vs Powered (Powered gives faster polling) ' A good example for regular polling ''PRI Get_Temperature '' if ow.get_temperature <> 0 '' temperature := ow.get_temperature '' ow.start_conversion(15) '' Returned temperature & $1ff is raw 9 bit value from device '' temperature >> 16 is decimal representation of high accuracy value * 100 VAR long pin, temperature, power, state, dly, crc, crcerror, poll long d500uS, d60uS, d750mS, d10uS PUB Start d500uS := clkfreq/2000 d60uS := clkfreq/16666 d10uS := clkfreq/100000 d750mS := clkfreq/100 * 75 State := 0 crcerror := 0 power := 0 ' Default to Parasite powered to be safe poll := 0 PUB Start_Conversion(ipin) if State == 0 Read_Power(ipin) temperature := 0 Reset WriteByte($CC) WriteByte($44) if power state := 2 ' Powered completion else outa[pin]~~ dira[pin]~~ ' Hard pull up for conversion power dly := cnt + d750mS state := 1 ' Parasite powered completion PUB Get_Temperature : val | remain, count, i, in[9] ' Substitute for (i > dly). Does not short cycle if (state == 1) and ((dly - cnt) < 0) ' If we are Parasite Powered we wait dira[pin]~ ' Remove hard pull up outa[pin]~ state := 3 if state == 2 ' If we are fully powered we poll for done dira[pin]~~ dira[pin]~ waitcnt(cnt + d10uS) if ina[pin] state := 3 if state == 3 Reset WriteByte($CC) WriteByte($BE) ' Read Scratchpad repeat i from 0 to 8 ' Read all 9 Bytes (including CRC) in[i] := ReadByte if crc == 0 ' If we got good data, process it temperature := in[0] | (in[1] << 8) if temperature <> 170 ' 170 == 85.0C == DS18S20 error condition Remain := in[6] Count := in[7] i := ((temperature & $1FE) << 7) - $40 ' Subtract 0.25 degrees i += ((Count-Remain) << 8) / (count) temperature += (((i >> 8) * 100) + (((i & $FF)* 100) >> 8)) << 16 state := 0 poll++ else ' Not a crc error, but a conversion error. Treat as same crcerror++ state := 0 Start_Conversion(pin) else ' If data was dud, try again crcerror++ state := 0 Start_Conversion(pin) val := Temperature PUB get_crcerror : val val := crcerror PUB get_power : val val := power PUB get_pollcnt : val val := poll ' Reads the power status of the sensor being polled to adjust the completion routine PUB Read_Power(ipin) pin := ipin Reset WriteByte($CC) WriteByte($B4) dira[pin]~~ dira[pin]~ waitcnt(cnt + d10uS) power := ina[pin] PRI Reset dira[pin]~~ waitcnt(cnt + d500uS) dira[pin]~ waitcnt(cnt + d500uS) crc := 0 PRI WriteByte(data) | i repeat 8 dira[pin]~~ if data & 1 dira[pin]~ waitcnt(cnt+d60uS) else waitcnt(cnt+d60uS) dira[pin]~ data >>= 1 PRI ReadByte : data | x repeat 8 dira[pin]~~ dira[pin]~ data >>= 1 data |= (ina[pin] << 7) waitcnt(cnt+d60uS) CRCByte(data) PRI CRCByte(data) | i repeat 8 i := crc ^ data crc >>= 1 data >>=1 if i & 1 crc := crc ^ $8C