Hallo allesamt Ich möchte ein bisschen mit 1-Wire Sensoren rumbasteln und habe daher ein paar Fragen zum Protokoll. Ich habe momentan noch keinen Logikanalysator und habe deswegen das Protokoll schon mal weitesgehend durchgearbeitet und Aktivitätsdiagramme für meine Programme gezeichnet. Ich erhoffe mir davon, dass ich dann die meisten Fehler garnicht erst mache :) Mein Diagramme habe ich in den Anhang gepackt? Kennt sich irgendjemand mit dem Thema aus? Und könnte vielleicht einmal drüber gucken, ob ich in diesem Schritt schon Fehler gemacht habe, oder ob ichs richtig verstanden habe? Konkret handelt es sich momentan um den Temperatur-Sensor DS18B20, von dem ich in meinen Diagrammen auch einige Funktionen benutze. Geplant ist momentan, dass ich vorher jeweils nacheinander immer einen Sensor an die Schaltung anschließe, die ID auslese und diese dann später hart im Programm codiere. Deshalb starte ich auch direkt mit dem Match Rom - Befehl. Was mir momentan allerdings nicht klar ist, ist wie ich es schaffe die ID des angeschlossenen Sensors auszulesen? So weit ich weiß nutzt man hierfür den den READ ROM - Befehl (bzw. SEARCH ROM bei mehreren Sensoren): Allerdingsist mir nicht klar, wie genau der Sensor hierauf antwortet. Kennst sich jemand mit dem Thema aus? Im Anhang habe ich auch noch mal meine Quellen angehängt. Viele Grüße Anon1234
schau mal hier: Beitrag "Vereinfache/Kompakte Libary für D18B20" Deine Ablaufdiagramme sind "nett" aber berücksichtigen keine Fehlerfälle (der Regelfall macht 90% des Codes aus, die Fehlerfälle die anderen 90% :-) 1wire ist nicht ganz trivial (vor allem das Enumerieren), und wenn man es so genial macht wie Peter Danegger, wird es noch un-trivialer...
Michael Reinelt schrieb: > (der Regelfall macht 90% des Codes aus, die Fehlerfälle die anderen 90% > :-) Komisch, bei mir ist das genau umgekehrt.
Marc Vesely schrieb: > Michael Reinelt schrieb: >> (der Regelfall macht 90% des Codes aus, die Fehlerfälle die anderen 90% >> :-) > > Komisch, bei mir ist das genau umgekehrt. Du hast recht, bei mir schwankt es auch. Vor allem abhängig von meiner Lederallergie.
Michael Reinelt schrieb: > schau mal hier: Beitrag "Vereinfache/Kompakte Libary für D18B20" > > Deine Ablaufdiagramme sind "nett" aber berücksichtigen keine Fehlerfälle > (der Regelfall macht 90% des Codes aus, die Fehlerfälle die anderen 90% > :-) Alles klar, danke für den Tipp, das werde ich mir dann mal angucken. Um was für Fehlerfälle handelt es sich dann hier? Sind dass dann Arbitrationfehler auf dem Bus, oder einfachh Fehler beim Enumerieren. Davon hab ich nämlich in den Datenblättern nichts gelesen. Weißt du wo ich mich darüber informieren kann?
Anon Anon schrieb: > Um was für Fehlerfälle handelt es sich dann hier? z.B. Kurzschluss-Erkennung beim detektieren des "presence pulse", oder beim enumerieren bit und komplementärbit beide 1. Mehr gibts aber glaub ich eh nicht.
Michael Reinelt schrieb: > schau mal hier: Beitrag "Vereinfache/Kompakte Libary für D18B20" Die Libary sieht ganz gut aus :) Aber weiß jemand wo ich diese Header-Dateien herbekomme: #include <stdlib.h> #include <stdint.h> #include <math.h> #include <util/delay.h> #include <util/atomic.h>
Anon Anon schrieb: > Aber weiß jemand wo ich diese Header-Dateien herbekomme: > #include <stdlib.h> > #include <stdint.h> > #include <math.h> > #include <util/delay.h> > #include <util/atomic.h> Die Frage wundert mich, weil das sind nur Standard-Header der GCC-AVR-Toolchain... Lass mich die Frage umdrehen: Wie sieht deine Entwicklungsumgebung aus? Womit compilierst du normalerweise?
Michael Reinelt schrieb: > Lass mich die Frage umdrehen: Wie sieht deine Entwicklungsumgebung aus? > Womit compilierst du normalerweise? Ich entwickle und compiliere mit Keil µVision. Allerdings mit einem 8051-Derivat. mit AVR kenne ich mich momentan noch nicht aus. (Also den Code kann ich schon lesen und verstehen, aber mehr hab ich mich da auch noch nicht reingearbeitet)
Anon Anon schrieb: > Ich entwickle und compiliere mit Keil µVision. Allerdings mit einem > 8051-Derivat. Sorry, damit kenn ich mich jetzt wieder gar nicht aus... > #include <stdlib.h> sollte der keil auch haben, sogar im Standard-Include-Pfad > #include <stdint.h> detto > #include <math.h> wird nur für float-berechnungen verwendet > #include <util/delay.h> das ist sehr AVR-Spezifisch, brauchst aber nur für die _dely_us() funktion, und es wird sicher was vergleichbares bei dir geben > #include <util/atomic.h> wird dzt. gar nciht verwendet
hey... hat zwar etwas gedauert, weil ich die letzte woche nicht so viel hatte, aber ich habe jetzt mal einen beispiel-code für den at89s52 geschrieben : meint ihr das passt jetzt so? die kurzschluss-abfrage habe ich jetzt auch eingebaut.
1 | ;------------------------------------------------------------------------ |
2 | ;Programdescription |
3 | ;------------------------------------------------------------------------ |
4 | ;--- |
5 | ;Program: |
6 | ; Test for two DS18B20 1-Wire Temperature Sensor, |
7 | ; which addresses are already defined in the code |
8 | ;--- |
9 | ;Date: 09/2014 |
10 | ;Programmer: Wall.Of.Death |
11 | ;--- |
12 | ;Used subroutines: |
13 | ; none |
14 | ;--- |
15 | ;Used registers, ports and memory addresses: |
16 | ; |
17 | ; Port 2.0 = DataLine of 1-Wire-Bus |
18 | ; |
19 | ; R0 is temp storage for everything |
20 | ; R1 is loopIndex_1 |
21 | ; R2 is loopIndex_2 |
22 | ; R3 is reserved |
23 | ; R4 is reserved |
24 | ; R5 and R6 are reserved for delay/timer |
25 | ; >> delaytime is set by R5 and R6 (R5 is LSB) |
26 | ; >> timer time till overflow = R5 and R6 together as a 16Bit value in µseconds |
27 | ; R7 is reserved as 1-Byte-Buffer for READ and WRITE on bus |
28 | ; |
29 | ; 20h.0 is reserved to temporary save the states of the bus |
30 | ; 20h.1 is reserved as 1-Bit-Buffer for READ and WRITE on the bus |
31 | ; |
32 | ; 7ch is read temperature (LSB) |
33 | ; 7dh is read temperature (MSB) |
34 | ; 7eh is current 1-Wire address index |
35 | ; 7fh is 1-Wire devices count |
36 | ; |
37 | ; internal storage from 80h to FFh is reserved for 1-wire addresses |
38 | ; every address is a 64 bit address |
39 | ; first address is from 80h to 87h |
40 | ; second address is from 88h to 90h |
41 | ; ... |
42 | ;--- |
43 | ;comments: |
44 | ; TODO 8Byte addresses |
45 | ; read |
46 | ; addresses |
47 | ; |
48 | ;changesLog: |
49 | ; date description |
50 | ; XX.09.2014 v1.0 communication with DS18B20-sensors, untested |
51 | ;--- |
52 | ;------------------------------------------------------------------------ |
53 | ;Initialization of constants |
54 | ;------------------------------------------------------------------------ |
55 | ; |
56 | ; |
57 | ;------------------------------------------------------------------------ |
58 | ;Interrupt-Vector |
59 | ;------------------------------------------------------------------------ |
60 | ; |
61 | org 0 ; begin of interrupt-vector >> reset |
62 | |
63 | jmp 0100h ; jmp initTimer |
64 | |
65 | org 001bh ; interrupt-Timer |
66 | |
67 | org 0100h ; end of interrupt-vector |
68 | ; |
69 | ;------------------------------------------------------------------------ |
70 | ;Initialization on-chip-periphery |
71 | ;------------------------------------------------------------------------ |
72 | ;------------------------------------------------------------------------ |
73 | ;Programm-Code |
74 | ;------------------------------------------------------------------------ |
75 | |
76 | $include(at89s53.inc) |
77 | |
78 | ; init sets addresses of 1-Wire devices |
79 | init: |
80 | mov 7eh,#80h ; 7eh = first address where 1-wire-addresses get saved |
81 | mov 7fh,#2 ; number of 1-Wire devices |
82 | mov r0,#80h |
83 | ; Device 1 |
84 | mov @r0,#12h |
85 | inc r0 |
86 | mov @r0,#34h |
87 | inc r0 |
88 | mov @r0,#56h |
89 | inc r0 |
90 | mov @r0,#78h |
91 | inc r0 |
92 | mov @r0,#90h |
93 | inc r0 |
94 | mov @r0,#98h |
95 | inc r0 |
96 | mov @r0,#76h |
97 | inc r0 |
98 | mov @r0,#54h |
99 | inc r0 |
100 | ; Device 2 |
101 | mov @r0,#0FFh |
102 | inc r0 |
103 | mov @r0,#00h |
104 | inc r0 |
105 | mov @r0,#0FFh |
106 | inc r0 |
107 | mov @r0,#00h |
108 | inc r0 |
109 | mov @r0,#0FFh |
110 | inc r0 |
111 | mov @r0,#00h |
112 | inc r0 |
113 | mov @r0,#0FFh |
114 | inc r0 |
115 | mov @r0,#00h |
116 | inc r0 |
117 | |
118 | ; main |
119 | main: |
120 | call getTemperature |
121 | call saveTemperature ; TODO |
122 | call temperatureOut ; TODO |
123 | call resetAddress |
124 | jmp main |
125 | |
126 | ; resets 1-wire-addresscounter to first address if all devices are iterated |
127 | resetAddress: |
128 | mov a,7fh ; devices / 1-wire-addresses count |
129 | mov b,#8 ; 8 Bytes per address |
130 | mul ab ; |
131 | add a,#80h ; e.g. #80h + (#8*#2) = #90h >> #80h = first address ; 8Bytes per address ; 2 addresses |
132 | cjne a,7eh,notLastAddress |
133 | mov 7eh,#80h ; address was last address >> reset to first |
134 | ret |
135 | notLastAddress: |
136 | ret |
137 | |
138 | ; returns the Temperature of the selected device |
139 | getTemperature: |
140 | call initializationProcedure |
141 | jb 20h.0,getTemperature ; no PRESENCE was detected |
142 | call matchRom |
143 | call convertT |
144 | call readScratchpad ; TODO |
145 | ret |
146 | |
147 | ; |
148 | saveTemperature: |
149 | ret |
150 | |
151 | ; |
152 | temperatureOut: |
153 | ret |
154 | |
155 | ;------------------------------------------------------------------------ |
156 | ;1-wire functions |
157 | ;------------------------------------------------------------------------ |
158 | |
159 | ; sends a RESET and waits 240µs for a PRESENCE |
160 | ; returns 0 if PRESENCE is detected |
161 | ; returns 1 if PRESENCE is not detected |
162 | initializationProcedure: |
163 | clr p2.0 ; RESET : |
164 | mov r5,#0E0h ; pull bus low |
165 | mov r6,#1h ; for 480µs |
166 | call delay ; |
167 | setb p2.0 ; PRESENCE |
168 | mov r5,#0F0h ; wait for 240µs |
169 | mov r6,#0h ; |
170 | call initTimer ; |
171 | waitLoop_1: |
172 | jnb p2.0,fallingEdge_1 ; during this time detect a falling Edge |
173 | jb TF1,noFallingEdge_1 ; or stop after the time |
174 | jmp waitLoop_1 |
175 | fallingEdge_1: |
176 | clr tr1 ; stop timer |
177 | clr 20h.0 ; save bus-state |
178 | jmp detectShortcut_1 |
179 | noFallingEdge_1: |
180 | clr tr1 ; stop timer |
181 | setb 20h.0 ; save bus-state |
182 | jmp detectShortcut_1 |
183 | detectShortcut_1: |
184 | mov r5,#9Ah ; wait for 410µs |
185 | mov r6,#1h ; |
186 | call initTimer ; |
187 | jnb p2.0, main ; if shortcut is selected jmp back to main |
188 | ret |
189 | |
190 | ; writes the MATCH ROM (55h) signal and the the 8Byte address |
191 | matchRom: |
192 | mov r7,#55h ; MATCH ROM |
193 | call writeByte ; |
194 | mov r2,#8 |
195 | write8BytesLoop_1: ; write 1-wire address |
196 | mov r0,7eh ; load current byte of the address |
197 | mov a,@r0 ; |
198 | mov r7,a ; |
199 | call writeByte ; write current byte of the address |
200 | inc 7eh ; inc "1-wire-addresspointer" |
201 | djnz r2,write8BytesLoop_1 |
202 | ret |
203 | |
204 | ;------------------------------------------------------------------------ |
205 | ;DS18B20 - functions |
206 | ;------------------------------------------------------------------------ |
207 | |
208 | |
209 | ; writes the CONVERT T (44h) signal for DS18B20 |
210 | convertT: |
211 | mov r7,#44h ; CONVERT T |
212 | call writeByte |
213 | ret |
214 | |
215 | ; reads the first two bytes of the scratchpad |
216 | readScratchpad: |
217 | mov r7,#0BEh ; READ SCRATCHPAD |
218 | call writeByte |
219 | call readByte ; only the first 2 bytes of the ccratchpad include |
220 | mov 7ch,r7 ; temperature information |
221 | call readByte |
222 | mov 7dh,r7 |
223 | ret |
224 | |
225 | ;------------------------------------------------------------------------ |
226 | ;READ / WRITE |
227 | ;------------------------------------------------------------------------ |
228 | |
229 | ; write the 8 bits of r7 to the bus |
230 | ; uses r1 for a loop |
231 | writeByte: |
232 | mov r1,#8 |
233 | write8BitsLoop_1: |
234 | mov a,r7 |
235 | anl a,#00000001b ; get lsb of a |
236 | call write ; write lsb of a |
237 | mov a,r7 ; rotate r7 |
238 | rr a ; to get next bit |
239 | mov r7,a ; |
240 | djnz r1,write8BitsLoop_1 |
241 | ret |
242 | |
243 | ; read the next 8 bits from the bus and write them into r7 |
244 | ; uses r1 for a loop |
245 | readByte: |
246 | mov r7,#0 |
247 | mov r1,#8 |
248 | read8BitsLoop_1: |
249 | mov a,r7 ; |
250 | rl a ; rotate a |
251 | call read ; read bit from bus |
252 | jb 20h.1,high_2 ; |
253 | orl a,#00000000b ; bit was low |
254 | jmp readByte_ |
255 | high_2: ; bit was high |
256 | orl a,#00000001b |
257 | readByte_: |
258 | mov r7,a |
259 | djnz r1,read8BitsLoop_1 |
260 | ret |
261 | |
262 | ; write lsb of a to bus |
263 | write: |
264 | jnz high_1 |
265 | mov r5,#3Ch ; LOW |
266 | mov r6,#0h ; >= 60µs |
267 | jmp write_ |
268 | high_1: |
269 | mov r5,#0Fh ; HIGH |
270 | mov r6,#0h ; <= 15µs |
271 | write_: |
272 | clr p2.0 ; pull bus LOW |
273 | call initTimer |
274 | jnb tf1,$ |
275 | setb p2.0 ; release bus |
276 | clr tr1 |
277 | ret |
278 | |
279 | ; read bus and write to 20h.0 |
280 | read: |
281 | clr p2.0 ; |
282 | mov th1,#0FFh ; pull bus LOW for min. 1µs |
283 | mov tl1,#0EFh ; |
284 | call initTimer ; |
285 | jnb tf1,$ |
286 | clr tf1 |
287 | setb p2.0 ; release bus |
288 | mov th1,#0FFh ; |
289 | mov tl1,#0F2h ; "start" timer again |
290 | waitLoop_2: |
291 | jnb p2.0,fallingEdge_2 ; during the next max 14µs detect signal on bus |
292 | jb TF1,noFallingEdge_2 ; or stop after the time |
293 | jmp waitLoop_2 |
294 | fallingEdge_2: |
295 | clr tr1 ; stop timer |
296 | clr 20h.0 ; save bus-state (LOW) |
297 | setb p2.0 |
298 | ret |
299 | noFallingEdge_2: |
300 | clr tr1 ; stop timer |
301 | setb 20h.0 ; save bus-state (HIGH) |
302 | ret |
303 | |
304 | ;------------------------------------------------------------------------ |
305 | ;Timer |
306 | ;------------------------------------------------------------------------ |
307 | |
308 | ;sets TimerValue to FFFFFFFF - time in µSeconds |
309 | ;inits and starts Timer |
310 | initTimer: |
311 | ; sets TimerValue to FFFFFFFF - time in µSeconds |
312 | mov a,#0FFh |
313 | clr cy |
314 | subb a,r5 |
315 | mov tl1,a |
316 | mov a,#0FFh |
317 | subb a,r6 |
318 | mov th1,a |
319 | |
320 | ; inits the timer |
321 | mov tmod,#00010000b |
322 | ; Timer 1 zählt jeden 12. Takt = 1MHz |
323 | ; 0 = keine externe Zählersteuerung durch Torschaltung |
324 | ; 0 = interner Zeitgeber |
325 | ; 01 = 16 Bit-Zähler |
326 | ; Timer 0 |
327 | ; 0000 = aus |
328 | clr tf1 ; overflow-flag zurücksetzen |
329 | setb tr1 ; Starten des Timers |
330 | ret |
331 | |
332 | ;sets TimerValue to FFFFFFFF - time in µSeconds |
333 | ;inits and starts Timer |
334 | ;and waits till Timeroverflow |
335 | delay: |
336 | call initTimer |
337 | jnb TF1,$ ; notify TimerOverflow |
338 | clr tr1 ; stop timer |
339 | ret |
340 | |
341 | end |
ich gehe davon aus, dass die adressen für die ds18b20-Geräte bekannt sind und diese im code später fest-codiert werden. allerdings weiß ich noch nicht, wie ich die adressen am einfachsten auslesen kann. Das prinzip vom search-rom habe ich nämlich momentan noch nicht ganz verstanden. kann mir hier jemand weiter helfen? alternativ habe ich überlegt mit den fertigen libraries von arduino die addressen auszulesen.
Anon Anon schrieb: > Das prinzip vom search-rom habe ich nämlich momentan noch nicht ganz > verstanden. mit "SearchRom 0xF0" kannst du den ROM-Code von allen Slaves am Bus ermitteln das erfordert aber einiges an Software einfacher ist der Befehl "ReadROM 0x33" der ließt direkt den ROM-Code vom angeschlossenen Slave aus (allerdings darf zu diesem Zeitpunkt nur EIN Slave am Bus hängen) Ablauf. 1. Reset Sequenz 2. den Befehl "ReadRom" senden 3. 8Bytes lesen (das ist dann der 48bit ROM-Code vom Slave) Gruss Uwe
:
Bearbeitet durch User
Für einen einzelnen Sensor (pro Leitung) benötigt man die Adresse überhaupt nicht. Da tut es auch SKIP ROM. Wär sinnvoll, damit anzufangen.
Anon Anon schrieb: > ich habe jetzt mal einen beispiel-code für den at89s52 geschrieben : Längerer Code passt besser in einen Anhang.
Uwe B. schrieb: > einfacher ist der Befehl "ReadROM 0x33" der ließt direkt den > ROM-Code vom angeschlossenen Slave aus > (allerdings darf zu diesem Zeitpunkt nur EIN Slave am Bus hängen) > > Ablauf. > 1. Reset Sequenz > 2. den Befehl "ReadRom" senden > 3. 8Bytes lesen (das ist dann der 48bit ROM-Code vom Slave) Hi Uwe, danke für die schnelle und gute Antwort. Das werde ich dann nacher gleich mal ausprobieren :) Du meinst aber sicherlich 64Bit oder? A. K. schrieb: > Längerer Code passt besser in einen Anhang. Alles klar, denke ich nächstes mal dran :)
Anon Anon schrieb: > Du meinst aber sicherlich 64Bit oder? ja...sorry war ein Tipfehler ROM-Code = 8 Bytes (64bit) 8bit : Family Code 48bit : Ser-Nr 8bit : CRC P.S. im Datasheet vom Dallas DS1820 ist ein Beispiel beschrieben wie man einen ROM-Search implementiert (in Textform) kannst da ja mal nachlesen falls du das auch implementieren willst
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.