www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 1-Wire Temperatursensor DS18S20 mit Atmega8 Ansteuern


Autor: Jonix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich versuche schon seit mehreren Wochen mit dem Atmega8 den digitalen 
1-Wire Temperatursensor DS18S20 anzusteuern und die Temperatur 
auszulesen.

Leider hat bis jetzt erst die Initialisierung geklappt, ich habe es noch 
nicht geschafft, dem Sensor ein brauchbares Byte zu entlocken.

Vielleicht kann mir ja einer von euch sagen, was ich falsch gemacht 
habe. Hier sind meine Lese- und Schreibroutinen, ich denke dass hier der 
Fehler versteckt ist:
Schreibe1:
out DDRD, Hi    ; Sensor Ausgang
cbi PORTD,7    ; Sensor 0
rcall Wait10    ; Warte 10µs
sbi PORTD,7    ; Sensor 1
rcall Wait58    ; Warte 58µs
ret

Schreibe0:
out DDRD, Hi    ; Sensor Ausgang
cbi PORTD,7          ; Sensor 0
rcall Wait10    ; 10µs warten
rcall Wait58    ; 58µs warten
out PORTD,7    ; Sensor 1µs Recovery Time
rcall Wait2    ; 2µs Recovery Time
ret

Lesen:
out DDRD,Hi    ; PORTD Ausgabe
out PORTD, Lo          ; Pulldown
rcall Wait2    ; 2 µs
out DDRD, Lo          ; PIND Eingang
rcall Wait10          ; Warte 10µs
rcall Wait2    ; Warte 2µs
in r24, PIND          ; Lese PIND
or r25, r24    ; Wert von Pin 7 in r25 schreiben
lsr r25      ; Eine Stelle nach rechts schieben
ret

Ein Fertig ausgelesenes Byte soll dann am Ende im Register r25 stehen.

Hier als Hilfe noch der Link zum Datenblatt des Sensors:
http://datasheets.maxim-ic.com/en/ds/DS18S20.pdf

Im Datenblatt steht außerdem, dass der Sensor bei der Ausgabe immer mit 
dem niedrigsten Bit anfängt, muss dann auch beim Schreiben eines Befehls 
mit dessen niedrigsten Bit anfangen?

Vielen Dank für eure Hilfe schon mal im Voraus

Autor: Wolfgang Schmidt (wsm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab auch damit (erfolgreich) experimentiert.

hast du eine Versorgungsspannung angeschlossen?

Während der AD-Wandlung braucht der 18S20 das.

Ohne die Versorgungsspannung klappt nur die Initialisierung.



W.

Autor: Jonix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke ich habe alles  korrekt angeschlossen.

Ich betreibe ihn  mit externer Stromversorgung, GND->GND, DQ->µC, 
VDD->+5V und mit 4,7k gegen DQ.

Autor: Andy H. (vinculum) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dazu gibt es ja jede Menge Code im Internet. Da würde ich das Rad nicht 
neu erfinden.

Autor: Jonix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Datenblatt des Sensors steht folgendes:
" To generate a Write 1 time slot, after pulling the 1-Wire bus low, the 
bus master must release the 1-Wire
bus within 15μs " ( http://datasheets.maxim-ic.com/en/ds/DS18S20.pdf )

Bedeutet "release the bus" das ich den µC Pin in Richtung Ausgang auf 1 
setze, oder dass ich den Pin als Eingang setzen soll?

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"release the bus" == Finger weg! == Eingang.
Der Code oben sollten passen.

Wegen der Reihenfolge:
Ich sende Bit 0 und schiebe dann 1 nach rechts.
Beim lesen schiebe ich 1 nach rechts und speichere in Bit 7.
Ergo immer kleinstes Bit zuerst.

Genereller Ablauf bei einem Device:
1. Bus reset
2. SKIP ROM Command (CCh)
3. Convert Command (44h)
4. 1 Sek warten.
5. Bus reset
6. SKIP ROM Command (CCh)
7. Read Scratchpad Command (BEh)
8. jetzt 2-9 Byte lesen (Temperatur + x + CRC)

Unbedingt das Timing einhalten.
Ein Oszi hilft.

Autor: Gim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ignoriert mich, wenn ich mich irre, aber man muss doch den DS18S20 ueber 
eine Adresse ansprechen, kennst Du diese und machst Du das richtig?

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Gim:
Ja, 1-Wire Slaves kann man über ihre Adresse ansprechen.
Die muss man aber vorher erst mal ermitteln.
Wenn nur ein Slave am Port hängt kann man sich den
Aufwand sparen (SKIP ROM).

Autor: mage (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
könntest du mal den ganzen code posten, weil ich bei 1Wire auch nicht 
richtig durchblicke und dein code gut kommentiert ist. Kleine Fehler 
stören nicht.

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, ich hatte deinen ASM Code nur kurz überflogen...
(ASM ist bei mir schon eine weile her...)
Mir sind da jetzt doch ein parr Dinge aufgefallen....

Wie hast du Hi und Lo definiert?
Sind das 2 Register die 0xff bzw. 0x00 enthalten?
Ich frage so blöd weil du out anstatt sbi/cbi verwendest...

Nach "Schreibe1:" und "Schreibe0:" bleibt der Port
als Ausgang konfiguriert. Laut pdf muss der Port aber
hochohmig werden -> Eingang.
Setze doch PORTD Bit 7 nach dem Reset auf 0 und
Schalte NUR noch DDRD Bit 7.

Was soll das machen? Bzw. was steht in r7?
Schreibe0:
[...]
out PORTD,7    ; Sensor 1µs Recovery Time
Oder hätte das vielleicht sbi sein sollen?

in "Lesen:" veroderst du jedes mal das gesamte PIND Register:
in r24, PIND          ; Lese PIND
or r25, r24    ; Wert von Pin 7 in r25 schreiben
lsr r25      ; Eine Stelle nach rechts schieben
Hast du sichergestellt das die restlichen Pins 0 haben?
Sonst streust du dir da munter irgendwelche Bits ein.
Außerdem blockierst du so den gesamten PORTD für weitere Nutzung...
Ein andi r24, 0x80 hilft.


Ansonsten Poste mal mehr Code.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Jonix (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure Antworten, dadurch bin ich auf sehr viele Fehler 
aufmerksam geworden.

Im Anhang ist mein ganzer Assembler Quellcode, ich hoffe er ist 
einigermaßen übersichtlich.
Verzeit bitte, dass ich bei den Befehlen jedes Bit einzeln mit rcall 
Befehlen übertrage, ich möchte das Programm erst einmal so einfach wie 
möglich halten und wenn es dann funktioniert mit der Vereinfachung und 
Optimierung beginnen.

@ Tim:
- ich wusste nicht, dass man die Datenrichtungsregister direkt mit 
"cbi/sbi" als Ausgang/Eingang konfigurieren kann, deswegen habe ich 
alles mit "out" gemacht, habe es jetzt abgeändert
- nach "Schreibe0" und "Schreibe1" DDRD als Eingang --> geändert
- Das "out" bei "Schreibe0" war ein Tippfehler --> geändert
- Schau mal ob du das mit dem andi so gemeint hast:
in r24, PIND         ; Lese PIND
andi r24,0b10000000  ; Bit 0-6 null setzen
or r25, r24          ; Wert von Pin 7 in r25 schreiben
lsr r25              ; Eine Stelle nach rechts schieben

Autor: Peter R. (pnu)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Es kommt vielleicht etwas spät, aber im Anhang meine funktionierende 
asm-Lösung

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> - ich wusste nicht, dass man die Datenrichtungsregister direkt mit
> "cbi/sbi" als Ausgang/Eingang konfigurieren kann, deswegen habe ich
> alles mit "out" gemacht, habe es jetzt abgeändert

Kommt auf den AVR und das gewünschte register an...
Cbi/sbi kann nur IO-Adressen 0x0..1F bearbeiten.
Da beim M8 der Port D auf 0x10..12 liegt (Siehe Register Summary) geht 
das.
Bei grösseren AVRs reicht dann teilweise in/out nicht mehr da
in/out nur 0x00..0x3f kann :-)

> - Schau mal ob du das mit dem andi so gemeint hast:
Ja, genau so.

ConT:
[..]
; Warte bis Temp. konvertieren fertig
Du liest hier nur den Pin zustand aus.
Die PDF sagt aber: "...the master can issue read-time slots after 
the..."
== rcall Lesen + auswertung
Habe ich mir gespart. 1 Sek warten war einfacher ;-)

> - nach "Schreibe0" und "Schreibe1" DDRD als Eingang --> geändert
> - Das "out" bei "Schreibe0" war ein Tippfehler --> geändert
Hmm... Dachte eigentlich das du NUR noch DDRD änderst.
Also nach deinem Stack init ein cbi PORTD, 7.
Und wenn der Bus 0 haben soll, einfach der Port via DDRD als
Ausgang setzten, ansonsten Eingang. Der Externe 4,7K Pullup
sorgt schon für die 1 auf der Leitung. Oder ist die zu lang?
Schreibe1:
[..]
Schreibe0:
[..]
rcall Wait2      ; 2�s Recovery Time
Lösche da den PORTD kram mal raus.
Wozu rcall Wait2?

Lesen:
rcall Wait2      ; 2 �s
cbi DDRD, 7      ; PIND Eingang
rcall Wait10    ; Warte 10�s
rcall Wait2      ; Warte 2�s
Du liest nach 2+10+2 µS, das könnte etwas (2µS) zu lang sein...
or r25, r24      ; Wert von Pin 7 in r25 schreiben
lsr r25        ; Eine Stelle nach rechts schieben
== Neues Bit vom Bus in Bit 7 dann alles 1 nach rechts (und Bit7 = 0)
So hast du nach 8 lesezugriffen: Bit 7 = 0, Bit 6-0 = Bits 7-1 vom Bus.
Bit 0 vom Bus ist weg. Also die 2 Zeilen drehen.

Autor: Jonix (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, ich habe das Programm mal abgeändert, dass es nach der Temperatur 
Konvertierung eine Sekunde wartet.
Jetzt habe ich auch verstanden wie du das mit dem "nur DDRD setzen bzw. 
löschen" meinst, habe ich auch geändert.

Wegen dem "Wait2" bei "Schreibe0", das steht doch im Datenblatt auf 
Seite 14 in dem Diagramm. Nach "Master Write 0 Slot" steht dort "2µs < 
Trec < ∞ ", deswegen warte ich 2 µs. Korrigiere mich bitte wenn ich mich 
irre.

Beim Lesen steht im Diagramm auch, dass der Master erst ganz am Ende 
Sampeln soll, grob abgelesen nach 14µs

Die Zeilen mit dem lsr habe ich jetzt vertauscht, du hast natürlich 
recht.


Der entscheidende Fehler lag aber an der Länge des Lese-Timeslots. Der 
Slot muss ja laut Datenblatt mindestens 60 µs + Recovery Time dauern, 
ich habe jedoch gleich nach dem lesen nach 14 µs mit dem Nächsten Bit 
begonnen, das war der Fehler.
Jetzt warte ich nach dem Lesen einfach noch mindestens 45 µs + mind. 1 
µs Recovery time, und sofort hat es funktioniert.

Also Vielen dank für eure großartige Hilfe, ohne euch hätte ich es 
trotzdem nicht geschafft

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.