-
        

Ergebnis 1 bis 3 von 3

Thema: Ansteuerung eines DS18S20

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672

    Ansteuerung eines DS18S20

    Anzeige

    Hallo,

    ich versuche mich gerade an der Ansteuerung eines DS18S20, es klappt aber nicht. Folgenden Code habe ich mit Hilfe des Datenblattes erstellt:

    Code:
    //Library zur Ansteuerung eines Temperatur-Sensors DS18S20
    void DS18S20_init   (volatile U8 *DataInPort, volatile U8 *DataOutPort, volatile U8 *DDR, U8 Pin);
    bool DS18S20_startTemp  (void);
    bool DS18S20_waitTemp  (void);
    bool DS18S20_readMemory  (void);
    bool DS18S20_getTemp   (int *result);
    bool DS18S20_resetPulse  (void);
    void DS18S20_sendByte  (U8 dataByte);
    bool DS18S20_readBit   (void);
    U8  DS18S20_readByte  (void);
    U8  DS18S20_scratchPadCRC (void);
     
    #define DS18S20_skipROM   0xCC
    #define DS18S20_convertTemp  0x44
    #define DS18S20_readScratchPad 0xBE
     
    
    volatile U8 *DS18S20inputPort;
    volatile U8 *DS18S20ddrPort;
       U8 DS18S20dataPin;
       U8 scratchPad[10];
    #define DS18S20input     *DS18S20ddrPort &= ~(1<<DS18S20dataPin)
    #define DS18S20output     *DS18S20ddrPort |= (1<<DS18S20dataPin)
    #define DS18S20dataIn     ((*DS18S20inputPort & (1<<DS18S20dataPin)) != 0)
     
    void DS18S20_init (volatile U8 *DataInPort, volatile U8 *DataOutPort, volatile U8 *DDR, U8 Pin)
    {
     DS18S20inputPort = DataInPort;
     DS18S20ddrPort = DDR;
     DS18S20dataPin = Pin;
     DS18S20input;
     *DataOutPort &= ~(1<<Pin);  // Pin löschen
    }
     
    bool DS18S20_startTemp (void)
    {
     if (DS18S20_resetPulse ())
     {
      DS18S20_sendByte (DS18S20_skipROM);
      DS18S20_sendByte (DS18S20_convertTemp);
      return (TRUE);
     }
     else
      return (FALSE);
    }
    bool DS18S20_waitTemp (void)
    {
     U8 timeout = 100;
     bool lastBit = FALSE;
     while ((!lastBit) & (timeout > 0))
     {
      _delay_ms (10);
      timeout--;
      lastBit = DS18S20_readBit ();
     }
     return (lastBit);
    }
    bool DS18S20_readMemory (void)
    {
     if (DS18S20_resetPulse ())
     {
      DS18S20_sendByte (DS18S20_skipROM);
      DS18S20_sendByte (DS18S20_readScratchPad);
      
      U8 i1;
      for (i1 = 0; i1 < 9; i1++)
      {
       scratchPad[i1] = DS18S20_readByte ();
      }
    return (TRUE);
      //return (DS18S20_scratchPadCRC () == scratchPad[8]);
     }
     else
      return (FALSE);
    }
     
    bool DS18S20_getTemp (int *result)
    {
     *result = 0;
     
     if (DS18S20_startTemp ())
      if (DS18S20_waitTemp ())
       if (DS18S20_readMemory ())
       {
        *result = scratchPad[1]<<8;
        *result = *result + scratchPad[0];
        return (TRUE);
       }
     
     return (FALSE);
    }
     
    
    bool DS18S20_resetPulse (void)
    {
     DS18S20output;
     _delay_us (500);
     DS18S20input;
     
     _delay_us (100);
     bool result = !(DS18S20dataIn);
     
     _delay_us (500);
     return (result);
    }
    void DS18S20_sendByte (U8 dataByte)
    {
     U8 i1;
     for (i1 = 0; i1 < 8; i1++)
     {
      DS18S20output;
      _delay_us (5);
      
      if ((dataByte & 1) != 0)
       DS18S20input;
      dataByte = dataByte>>1;
      
      _delay_us (60);
      DS18S20input;
      _delay_us (5);
     }
    }
    bool DS18S20_readBit (void)
    {
     DS18S20output;
     _delay_us (5);
     
     DS18S20input;
     _delay_us (15);
     bool result = DS18S20dataIn;
     _delay_us (45);
     return (result);
    }
    U8 DS18S20_readByte (void)
    {
     U8 result = 0;
     U8 i1;
     for (i1 = 0; i1 < 8; i1++)
     {
      result = result>>1;
      if (DS18S20_readBit ())
       result |= 0x80;
     }
     return (result);
    }
    U8 DS18S20_scratchPadCRC (void)
    {
     U8 ByteCount;
     U8 CRC = 0;
     
     for (ByteCount = 0; ByteCount < 8; ByteCount++)
     {
      U8 PruefByte = scratchPad[ByteCount];
      U8 BitCount = 8;
      for (BitCount = 0; BitCount < 8; BitCount++)
      {
       U8 BitWert = (CRC ^ PruefByte) & 0x01;
       if (BitWert == 0x01)
        CRC = CRC ^ 0x18;  // 0x18= X^8+X^5+X^4+X^0
       CRC = 0x7F & (CRC>>1);
       if (BitWert == 0x01)
        CRC = CRC | 0x80;
       PruefByte = PruefByte>>1;
      }
     }
     return (CRC);
    }
    Wenn ich die Funktion DS18S20_readMemory aufrufe, erhalte ich vom Sensor ausschließlich high als Bit-Daten. Ich habe meinen Code schon mit etlichen aus dem Web verglichen, und er ist eigentlich gleich. Wahrscheinlich sehe ich mal wieder den Wald vor lauter Bäumen nicht.

    Was funktioniert ist der Reset-Puls und die darauffolgende presence pulse Erkennung. Der Sensor zieht die Leitung auf Low. Wenn ich die Wartezeit für das low zu kurz (10µS), oder zu lange (200µS) mache, wird das low schon nicht mehr erkannt. Wenn ich den Sensor abklemme, bleibt die Leitung natürlich auch high.
    Allerdings zieht er die Leitung auch auf low, wenn ich den Reset-Puls z.B. nur 100µS auf low halte. Allerdings nicht immer.

    Aber dann wars dass auch schon. Nach dem Reset bekomme ich keine Reaktion mehr vom Sensor. Ich habe keine Ahnung, wo ich noch suchen soll. Mit den Delay-Zeiten habe ich schon stundenlang gespielt. Der Sensor will mir einfach keine Daten senden.
    Das ganze läuft auf einem Attiny45 mit internem Takt. Ich lasse eine LED mit _delay_ms (1000) blinken und der Sekundentakt scheint gut zu passen. Der Clock und die delay.h ist also scheinbar richtig konfiguriert. (sonst würde das mit dem Reset-Puls und der presence-Erkennung wohl auch nicht zu funktionieren)

    Der Fehler scheint also in den Sende- Und Empfangs-Funktionen zu liegen, aber die habe ich schon 1000x durchgeschaut. Wo könnte ich noch suchen?

    Viele Grüße
    Andreas

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672
    Guten morgen,

    hier mal ein Bild vom Aufbau:

    Klicke auf die Grafik für eine größere Ansicht

Name:	Foto.jpg
Hits:	8
Größe:	64,3 KB
ID:	26086

    Alles noch auf dem STK mit kurzen Kabeln, um Fehler mit zu langen Kabeln, etc. während der Entwicklung vorzubeugen. Der DS18S20 bekommt seine Spannungsversorgung ebenfalls über das STK. Den Zwei-Draht-Anschluss inkl. Versorgungsspannung über die Datenleitung möchte ich erst probieren, wenn die Kommunikation läuft.

    Viele Grüße
    Andreas

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    672
    Hallo,

    ich habe die Ursache des Problems gefunden. Nur der vollständigkeit halber, falls jemand anderes ein ähniches Problem haben sollte:

    Ich habe den ATtiny45 mit dem internen RC-Oszillator und gesetztem CKDIV8 Bit laufen lassen. Also FCPU = ca. 1 MHz. Das ist aber scheinbar zuwenig, um die Delays, die der DS18S20 benötgit genau genug einzuhalten. Nach dem löschen des CKDIV8-Bits und einer Run-Time-Geschwindigkeit von 8MHz läuft das Ganze nun einwandfrei.

    Viele Grüße
    Andreas

Ähnliche Themen

  1. Ansteuerung eines LCD
    Von Bierseppi im Forum Elektronik
    Antworten: 3
    Letzter Beitrag: 21.06.2011, 15:13
  2. PC-Ansteuerung eines Wechselstrommotors
    Von kali2 im Forum Motoren
    Antworten: 0
    Letzter Beitrag: 11.12.2007, 16:18
  3. Ansteuerung eines Bildschirmes
    Von Killer im Forum Elektronik
    Antworten: 12
    Letzter Beitrag: 12.08.2007, 21:25
  4. ansteuerung eines schrittmotors
    Von merlin63 im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 3
    Letzter Beitrag: 29.03.2005, 15:11
  5. Ansteuerung eines ADC0820
    Von Trabukh im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 08.01.2005, 21:46

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •