Was habe ich falsch gemacht! Oder ist mein Sensor defekt? // Sensor-Reset uint8_t reset(void) { DQ_DDR|=(1<<DQ_uC); // DQ_uC als Ausgang setzen DQ_PORT&=~(1<<DQ_uC); // DQ_uC an DQ_PORT auf 0 setzen _delay_us(480); DQ_DDR&=~(1<<DQ_uC); // DQ_uC als Eingang setzen DQ_PORT|=(1<<DQ_uC); // DQ_uC an DQ_PORT auf 1 setzen _delay_us(60); if(!(DQ_PIN & (1<<DQ_uC))) // Erfüllt wenn DQ_uC auf 0 liegt { return(1); } return(0); } Diese Funktion sollte eine 1 zurückgeben, es kommt aber immer eine 0 zurück. Ich kann keinen. Wenn ich extern mit einer Drahtbrücke den DQ_uC Pin auf GND lege kriege ich eine 1 zurück. Die Funktion scheint also zu stimmen.
Stimmen die Zeiten in den delay Funktionen? Fuses, F_CPU und kompilieren mit Optimierung AN prüfen. Wenn das nix hilft, ich habe einen DS18S20 hier und kann am Wochenende auch mal testen. Der funktioniert auch, denn dieses Jahr hatte ich schon mal ein DS18S20 Problem hier im Forum debuggt (#1). Müsstest dann nur erzählen/zeichnen, wie der DS18S20 bei dir angeschlossen ist. #1 Beitrag "DS18S20, Atmega8 und Winavr"
>DQ_DDR&=~(1<<DQ_uC); // DQ_uC als Eingang setzen >DQ_PORT|=(1<<DQ_uC); // DQ_uC an DQ_PORT auf 1 setzen Wenn ich mich auf die Schnelle nicht vertue, schaltetst Du mit der letzten Zeile den pull-up-widerstand ein; am EingangsPIN wird dann natürlich eine 1 gemessen, sofern die externe Beschaltung den pin nicht runterzieht.
Es könnte sein, dass die letzte Pause länger sein muss. Bevor der Status zurueckgegeben wird, muss eine Pause der Länge "J" (1wire app note von Maxim) abgewartet werden. Zumindest habe ich das mal in meiner verwendeten 1wire-Bibiothek so geändert, da ich auch mal das Problem hatte. Zumindest funktioniert es bei so einwandfrei. Du musst ja mindestens 60us warten. Ich warte bei mir 480us auf den presence pulse, was eigentlich zu lange ist, wie ich gerade im Datenblatt nachgeschaut habe. Also mit 180us Pause (statt Deiner 60us) müsstest Du genau drin liegen. Das werde ich bei mir nochmal überprüfen müssen ...
@ Lutz: Soweit ich das Datenblatt richtig deuten, zieht man den DQ-Pin des DS18S20 480µs auf low, "released" die Leitung für 15-60µs und wartet darauf, dass der Sensor mit seinem "Presence Pulse" von 60-240µs die Leitung auf LOW zieht.
Da hast Du recht. Vielleicht bin ich bisher fälschlicherweise von allerhand falschen Voraussetzungen ausgegangen, wie z.B. daß Du einen AVR uC ATMega (z.B. ATMega 168) benutzt. Den 4k7 Pullup, der den Bus nach dem reset wieder "hochholt", wird ja bestimmt vorhanden sein. Der Master muß für mindestens 480 us den DS18S20 low ziehen. Versuch spaßeshalber mal _delay_us(520) statt der 480. Bei ATMegas gilt: Wenn ein Pin im DDR auf Eingang (DDRpin=0) geschaltet wurde und danach im PORT eine 1 (PORTpin=1) geschrieben wurde, wird an diesem Eingang der interne Pullupwiderstand aktiviert. Und das machst Du unnötiger Weise in der zweiten Zeile (vermute ich). Interessant wäre es, wenn Du die #defines Deiner pins posten könntest. >DQ_DDR&=~(1<<DQ_uC); // DQ_uC als Eingang setzen >DQ_PORT|=(1<<DQ_uC); // DQ_uC an DQ_PORT auf 1 setzen Pullup macht schon der 4k7 am Bus. Das der interne Pullup und der externe 4k7 Pullup sich nun in die Haare kriegen (interner Pullup treibt stärker als der DS18S20 lowziehen kann) halte ich für unwahrscheinlich, da der interne Pullup der Größere ist.
Der interne Pullup stört nicht weil viel zu gross. Interessanter ist in dieser Hinsicht das andere Ende, auch wenn das hier nicht die Ursache ist: Wenn ein als Open Collector zu verwendender Portpin erst als Ausgang definiert und dann runtergezogen wird, dann zieht er u.U. erst einmal kurz aber knackig hoch. Da ist dringend die umgekehrte Reihenfolge empfohlen, wobei man eine solchen Pin auch gleich anfangs dauerhaft auf PORTxy=0 setzen und danach ausschliesslich mit der Richtung steuern kann.
1 | #define DQ_PIN PINB
|
2 | #define DQ_uC PB2
|
3 | #define DQ_DDR DDRB
|
4 | #define DQ_PORT PORTB
|
5 | |
6 | #define F_CPU 8000000
|
>DQ_DDR|=(1<<DQ_uC); // DQ_uC als Ausgang setzen
heißt mit Deinen #defines
DDRB |= (1<<PB2);
^^^
=> Muß aber DDB2 heißen.
Schau Dir mal die anderen #defines und das Datenblatt (speziell also die
PORTx-, DDRx- und PINx-Register sowie ihre Bedeutung) an.
Die Zeile
if(!(DQ_PIN & (1<<DQ_uC)))
sieht dann auch nicht so gut aus ...
Lutz wrote: > DDRB |= (1<<PB2); > ^^^ > => Muß aber DDB2 heißen. Kann, muss aber nicht, denn das ist so oder so nichts anderes als (1<<2). Grad wenn man Portpins zentral per #define zuordnet ist es bloss unnütze Arbeit, da noch zwischen PINxy, PORTxy und DDRxy zu unterscheiden.
Da ist natürlich was dran, obwohl das natürlich (wie so vieles) Geschmackssache ist. Aber wenn man das konsequent durchzieht, warum nicht. Das Problem ist aber, das man (zumindest als Anfänger) den Unterschied zwischen DDRx, PORTx und PINx so gar nicht wahrnimmt ("es funktioniert doch, wo ist denn das Problem?"), was früher oder später garantiert zu gravierenden Problemen führt.
hab mal das beispiel hex file auf mein entwicklungsboard geflasht! temperatur sensor funktioniert einwandfrei! leider hab ich von dem hex file keine sourcen ;-( (habe das EASY AVR 5A)
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.