Ich habe einen DS1820 an einem 90S8535 an dem PORTD Pin17 (PD3) angeschlossen. Als Quarzfrequenz verwende ich 8Mhz. Ich weiss nicht wo da der Fehler noch liegen könnte. Wenn ich Daten in den Controller einlesen möchte, dann muss ich doch das DDRD Register auf 0xFF setzen oder?
Wenn du DDR auf high setzt ist das normal ein Ausgang den du setzen kannst.
Was bei 1-Wire niemals vorkommen darf: Dass der Controller die Leitung hoch- aber das 1-Wire-Device sie runterzieht. Der könnte leicht dabei Schaden nehmen. Prinzip: Beide Seiten ziehen immer nur die Leitung runter, nur der Widerstand zieht sie hoch. Einzig wenn der Sensor 2-beinig ohne eigenen VCC-Anschluss betrieben wird ("parasitär"), dann ist in der Messphase mehr Strom nötig als der Widerstand liefern kann, und genau und nur dann darf der Controller selber die Leitung aktiv nach oben ziehen. In diesem Code kommt jedoch der Zustand PORT.x=1,DDR.x=1 vor, und genau das sollte nicht sein. Korrekt ist also: PORT.x bleibt permanent festgenagelt auf 0. Will der Controller die Leitung runterziehen, setzt er DDR.x=0, will er sie loslassen, dann DDR.x=1. Den Rest erledigt der zwingen notwendige externe Pullup-Widerstand.
> ... runterziehen, setzt er DDR.x=0, will er sie loslassen, dann DDR.x=1.
Sorry, natürlich andersrum.
Vielen Dank A.K. Ich habe die Funktion nochmal überarbeitet. char ResetDS1820(void) { DDRD.2=1; // PORTD.2 --> OUTPUT PORTD.2 = 0; // PORTD.2 den Wert 0 ausgeben delay_us(500); // Zeitverzögerung von 500us PORTD.2 = 1; // PORTD.2 den Wert 0 ausgeben delay_us(70); // Zeitverzögerung von 70us DDRD.2=0; // PORTD.2 --> INPUT presence = PIND.2; // Signal mit PIND.2 einlesen und der Variable // presence zuweisen delay_us(250); // Zeitverzögerung von 250us DDRD.2=1; // PORTD.2 --> OUTPUT return presence; // Ausgabe von presence }//--> 0=presence, 1=no part Wenn ich presence ausgebe, dann erhalte ich auf meinem Display den Wert 0. Somit musste doch die Funktion korrekt sein. Das heisst doch auch, dass der DS1820 funktioniert oder?
Achso wenn ich dich richtig verstanden habe, dann setzt man permanent PORTD.2 auf logisch NULL. Mit DDRD.2=1 und DDRD.2=0 kann man wählen zwischen INPUT und OUTPUT.
Korrekt. Die Beispiele von Dallas helfen dabei nicht sonderlich, weil die immer von 8051-ern ausgehen, deren I/O-Ports gänzlich anders arbeiten. Vielleicht hilfreich: Beitrag "DS1820, DS18B20 in C"
Was meinst du mit Korrekt. Ist meine Funktion ok so, oder meinst du meinen letzten Beitrag?!
Den letzten Beitrag, nicht die Funktion. Nur halt andersrum, d.h. "Mit DDRD.2=0 / DDRD.2=1 kann man wählen zwischen INPUT / OUTPUT."
Ich habe mir den 1wire Code dort heruntergeladen. Die Funktion ResetDS1820 habe ich gleich mal bei mir ausprobiert. Ich erhalte da immer den Wert 2. Verstehe ich nicht. Hast du einen C-Code zu dem DS1820 geschrieben? #ifndef W1_PIN #define W1_PIN PORTD.2 #define W1_IN PIND #define W1_OUT PORTD #define W1_DDR DDRD #endif unsigned char w1_reset(void) { unsigned char err; err = 0x00; W1_OUT &= ~(1<<W1_PIN); W1_DDR |= 1<<W1_PIN; delay_us(480); // 480 us W1_DDR &= ~(1<<W1_PIN); delay_us(66); err = W1_IN & (1<<W1_PIN); // no presence detect delay_us(480-66); if( (W1_IN & (1<<W1_PIN)) == 0 ) // short circuit err = 1; return err; }
Du mixt da vermutlich zwei verschiedene Compiler. Der Danegger'sche Code ist für WinAVR, die Definition W1_PIN=PORTD.2 passt dazu jedoch nicht. Folglich dürfte (1<<W2_PIN) Unfug sein.
Ich habe die Funktion nochmals auf den CodeVision_AVR abgestimmt. An Pin PD2 ist die Datenleitung vom DS1820 angeschlossen. #define W1_PIN PORTD.2 // Ausgang #define W1_IN PIND.2 // Eingang #define W1_OUT PORTD.2 // Ausgang #define W1_DDR DDRD.2 // die Richtung kann hiermit bestimmt werden. unsigned char w1_reset(void) { unsigned char err; err = 0x00; W1_OUT &= ~(W1_PIN); W1_DDR |= W1_PIN; delay_us(480); // 480 us W1_DDR &= ~(W1_PIN); delay_us(66); err = W1_IN & (W1_PIN); // no presence detect delay_us(480-66); if( (W1_IN & (W1_PIN)) == 0 )// short circuit err = 1; return err; } Leider erscheint auf meinem Display eine "1". Dies bedeutet DS1820 wurde nicht erkannt. Warum eigentlich "W1_PIN" und "W1_IN"? Es kann sein das ich bei der Definition noch einen Fehler habe. ich weiss allerdings nicht wo.
Mit #define W1_IN 2 // Eingang W1_OUT &= ~(1<<W1_PIN); sollte es bei jedem Compiler funktionieren. Die Codevision-Technik ist eine proprietäre Falle.
So ich habe mal das ganze ohne define erstellt. unsigned char w1_reset(void) { unsigned char err; err = 0x00; PORTD.2=0; DDRD.2=1; delay_us(480); DDRD.2=0; delay_us(66); err = PIND.2; delay_us(480-66); if( (PIND.2) == 0 ) err = 1; return err; } Wenn ich diese Funktion ausführe, dann erhalte ich auch den Wert "0". Also funktioniert doch das ganze oder?
W1_OUT &= ~(1<<W1_PIN); --> PORTD.2=0; W1_DDR |= 1<<W1_PIN; --> DDRD.2=1; W1_DDR &= ~(1<<W1_PIN); --> DDRD.2=0; W1_IN & (1<<W1_PIN); --> PIND.2 Stimmt meine Interpetation so?
Vielen Dank A.k:! Der DS1820 läuft bei mir jetzt. Bin jetzt voll happy. Nur noch eine Sache hätte ich da, ich kann nur ganze Temperaturen darstellen, wie z.B. 21 C°. Was muss ich tun, damit ich z.B. so einen Wert 21.5 C° auslesen kann?
Welcher genau, 18S20 oder 18B20? Der 18S20 liefert von Haus aus halbe Grade im normalen Register und lässt sich auf Sechzehntel aufdröseln, der 18B20 liefert von Haus aus schon Sechzehntel. Steht alles schön im Datasheet.
Laut Dallas ist der DS18S20 kompatibel mit dem DS1820, also ist das Temperatur-Register in halben Graden gespeichert. Mehr Bits geht mit Hilfe rines zweites Registers, aber ich habe keine Lust dir das ganze Datasheet vorzulesen, da steht da nämlich haarklein drin.
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.