Forum: Mikrocontroller und Digitale Elektronik 1-Wire Protokollablauf


von Anon A. (anon1234)



Lesenswert?

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

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Michael Reinelt schrieb:
> (der Regelfall macht 90% des Codes aus, die Fehlerfälle die anderen 90%
> :-)

 Komisch, bei mir ist das genau umgekehrt.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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.

von Anon A. (anon1234)


Lesenswert?

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?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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.

von Anon A. (anon1234)


Lesenswert?

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>

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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?

von Anon A. (anon1234)


Lesenswert?

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)

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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

von Anon A. (anon1234)


Lesenswert?

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.

von Uwe B. (derexponent)


Lesenswert?

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
von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Anon Anon schrieb:
> ich habe jetzt mal einen beispiel-code für den at89s52 geschrieben :

Längerer Code passt besser in einen Anhang.

von Anon A. (anon1234)


Lesenswert?

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 :)

von Uwe B. (derexponent)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.