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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
title "Outside sensor"
list p=16F88, b=8, r=dec
#include "p16f88.inc"
errorlevel -302, -306
#define IOPORT PORTA,7 ;I/O port used for 1-wire line
;1-wire ROM commands
#define READROM 0x33
#define SKIPROM 0xCC
;1-wire FUNCTION commands
#define CONVERTT 0x44
#define READSCRATCHPAD 0xBE
;1-wire family codes for supported temperature sensors
#define DS_FAM_DS18S20 0x10
#define DS_FAM_DS18B20 0x28
;Return codes, controlling when to perform the next step
#define DONE 0 ;Next step after one second
#define CONTINUE 1 ;Next step as soon as possible
extern float1, float2, flags, temp, StoreOutTemp
UDATA
sensorstage res 1
#define ds18b20 sensorstage,7
#define restart sensorstage,6
lsbstorage res 1
#define OutsideTemp flags,0 ;Keep in sync with gateway.asm
#define OutsideInvalid flags,1 ;Keep in sync with gateway.asm
global Temperature
Temperature CODE
Temperature skpz ;Zero bit indicates no message in prog
goto Restart ;Sequence interrupted by OT message
btfsc restart
clrf sensorstage
;Split up the temperature measurement into several short steps,
;each less than 1ms. That way the main loop is allowed to run
;frequently enough for it to be able to do all the necessary
;processing in time, like clearing out the serial receive
;register.
movlw high StageTable
movwf PCLATH
movfw sensorstage
andlw b'11111'
addlw low StageTable
skpnc
incf PCLATH,F
incf sensorstage,F ;Determine next step of the process
movwf PCL ;Jump to the current step
StageTable goto PresencePulse ;Step 0 - Transmit a reset pulse
goto SkipRom ;Step 1 - Address all devices on the bus
goto Measure ;Step 2 - Start a measurement
retlw DONE ;Step 3 - Allow time for measurement
goto PresencePulse ;Step 4 - Transmit a reset pulse
goto ReadRom ;Step 5 - Send Read ROM command
goto ReadFamily ;Step 6 - Read device family code
goto PresencePulse ;Step 7 - Transmit a reset pulse
goto SkipRom ;Step 8 - Address all devices
goto ReadCommand ;Step 9 - Send Read Scratchpad command
goto ReadLSB ;Step 10 - Read temperature value, LSB
goto ReadMSB ;Step 11 - Read temperature value, MSB
goto Restart ;Step 12 - Start over (never reached)
PresencePulse bcf IOPORT ;Prepare the output latch
bsf STATUS,RP0
bcf IOPORT ;Drive the output port low
call Delay480 ;Wait for the minimum reset duration
bsf STATUS,RP0
bsf IOPORT ;Release the I/O port
bcf STATUS,RP0
call Delay60 ;Allow the device time to respond
btfsc IOPORT ;Check the 1-wire line
goto NoDevice
call Delay240 ;Wait for the presence pulse to end
retlw CONTINUE
NoDevice bsf OutsideInvalid ;Outside temperature is not valid
goto Restart ;Start the sequence from the top
Measure movlw CONVERTT ;Initiate temperature conversion
call WriteByte ;Send the command on the 1-wire bus
retlw DONE ;Give devices time to do the conversion
ReadFamily call ReadByte ;Read family code from the 1-wire bus
movfw temp
sublw DS_FAM_DS18S20 ;Check if the sensor is a DS18S20
skpnz
retlw CONTINUE ;Found a DS18S20
movfw temp
sublw DS_FAM_DS18B20 ;Check if the sensor is a DS18B20
skpz
goto NoDevice ;Not a supported temperature sensor
bsf ds18b20 ;Found a DS18B20
retlw CONTINUE
ReadCommand movlw READSCRATCHPAD ;The scratchpad contains the temerature
goto WriteByte ;Send the command on the 1-wire bus
ReadLSB call ReadByte ;Read the first scratchpad byte
movfw temp
movwf lsbstorage ;Save the byte for later use
retlw CONTINUE
ReadMSB call ReadByte ;Read the second scratchpad byte
btfsc ds18b20 ;Check which sensor type was found
goto HighPrecision ;A DS18B20 stores the value differently
rrf temp,W ;Sign of the temperature value
rrf lsbstorage,W ;Determine the full degrees
movwf float1
clrf float2
rrf float2,F ;Determine the half degrees
goto Success
HighPrecision swapf lsbstorage,W ;Get the 1/16 degrees in the high nibble
andlw b'11110000'
movwf float2 ;Store as outside temperture low byte
swapf temp,W ;Get the upper nibble of the degrees
andlw b'11110000'
movwf temp ;Save for later use
swapf lsbstorage,W
andlw b'1111' ;Get the lower nibble of the degrees
iorwf temp,W ;Combine with the saved upper nibble
movwf float1 ;Store as outside temperature high byte
Success bsf OutsideTemp ;Temperature measurement completed
bsf OutsideInvalid ;Invalid until validity is checked
xorlw 85 ;Test against powerup value
skpnz
goto Restart ;Not a valid measurement
lcall StoreOutTemp ;Store the measurement
retlw CONTINUE
Restart bsf restart ;Don't clear sensorstage for debugging
retlw DONE
Delay480 call Delay240 ;480 = 2 * 240
Delay240 movlw 240 - 8 ;Value for 240uS delay (compensated)
goto Delay ;Wait for the specified amount of time
Delay60 movlw 60 - 6 ;Value for 60uS delay (compensated)
Delay bsf STATUS,RP0 ;Bank 1
bcf PIE1,TMR2IE ;Disable interrupt from timer 2
subwf PR2,W ;Calculate the start value
bcf STATUS,RP0 ;Bank 0
addlw 10 ;Overhead for starting and stopping
movwf TMR2 ;Load the timer
bsf T2CON,TMR2ON ;Start timer 2
WaitTimer2 btfss PIR1,TMR2IF ;Check if timer 2 expired
goto WaitTimer2 ;Wait some more
bcf T2CON,TMR2ON ;Stop timer 2
bcf PIR1,TMR2IF ;Prevent unwanted interrupt
return
Delay15 call Delay5 ;15 = 3 * 5
Delay10 call Delay5 ;10 = 2 * 5
Delay5 nop ;Wait 1 us
return ;Subroutine Call + Return = 2us + 2us
ReadByte call ReadNibble ;Read 4 bits from 1-wire bus
ReadNibble call ReadBit ;Read 1 bit from 1-wire bus
call ReadBit ;Read 1 bit from 1-wire bus
call ReadBit ;Read 1 bit from 1-wire bus
ReadBit bcf IOPORT ;Prepare output latch
bsf STATUS,RP0 ;TRIS register is in Bank 1
bcf IOPORT ;Drive the 1-wire line low
clrc ;Prepare carry while waiting
bsf IOPORT ;Release the 1-wire bus
bcf STATUS,RP0 ;Back to bank 0
call Delay10 ;Allow device time to write the bit
btfsc IOPORT ;Read the 1-wire bus
setc ;Device wrote a "1"
rrf temp,F ;Shift bit into the result varaible
movlw 45 ;Maximum time a device drives the bus
call Delay ;Wait for the device to release the bus
return
ReadRom movlw READROM ;Command to read a device's ROM code
goto WriteByte ;Send the command on the 1-wire bus
SkipRom movlw SKIPROM ;Address all devices on the 1-wire bus
WriteByte movwf temp ;Temporarily store the 1-wire command
call WriteNibble ;Write 4 bits to the 1-wire bus
WriteNibble call WriteBit ;Write 1 bit to the 1-wire bus
call WriteBit ;Write 1 bit to the 1-wire bus
call WriteBit ;Write 1 bit to the 1-wire bus
WriteBit rrf temp,F ;Set carry to least significant bit
WriteSlot bcf IOPORT ;Prepare the output latch
bsf STATUS,RP0
bcf IOPORT ;Drive the 1-wire line low
skpnc ;Carry contains the bit to send
bsf IOPORT ;Release the 1-wire line
movlw 60 - 10 ;Value for 60uS delay (compensated)
call Delay ;Bit duration
bsf STATUS,RP0 ;Bank 1
bsf IOPORT ;Float the 1-wire line, if necessary
bcf STATUS,RP0 ;Bank 0
retlw CONTINUE
end
|