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