Forum: Mikrocontroller und Digitale Elektronik USI TWI Probleme mit DS1631 Temperatursensor


von Christoph R. (christoph63)


Lesenswert?

Hallo zusammen,

Ich versuche seit einiger Zeit den DS1631 Temperatursensor am USI TWI 
des Atmega169 zum laufen zu bekommen.
Im wesentlichen verwende ich die Appnote AVR310, was bei dem vorher 
verwendeten MAX6633 Temperatursensor auch gut geklappt hat.
Für den DS1631 ist nun um ein Register zu lesen eine wiederholtes Start 
notwendig, was eine Abwandlung der Funktion unsigned char 
USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char 
msgSize) aus der AppNote erforderte.
Mein Problem ist jetzt folgendes:
Ich kann wunderbar in die Register des DS1631 schreiben, aber das 
Auslesen der beiden Temperaturregister klappt nur beim ersten mal. 
Danach ist kein Auslesen mehr möglich, wobei Schreiboperationen 
weiterhin mit einem ACK quittiert werden. Dabei findet der Fehler immer 
an der Stelle statt, wo die Addresse des DS1631 nach der zweiten 
Start-Condition zum zweiten mal übertragen wird, aber diesmal mit dem 
letzten Bit gesetzt um einen Lesevorgang zu signalisieren.
Ich probier hier schon seit Tagen rum und bekomm das Problem einfach 
nicht in den Griff.
Falls jemand ähnliche Probleme hatte und Abhilfe weis, so bin ich für 
jeden Tip dankbar!

Beste Grüße, Christoph

von TT (Gast)


Lesenswert?

Etwas Quellcode von dir wäre ganz nützlich ;-)

von Christoph R. (christoph63)


Lesenswert?

Hier der Quellcode ab der Stelle an der die wiederholte Startcondition 
gesendet wird:

//Need to repeat the start condition to change to read mode
    /* Release SCL to ensure that (repeated) Start can be performed */
  PORT_USI |= (1<<PIN_USI_SCL);                     // Release SCL.
  _delay_us( T4_TWI );
    /* Generate Start Condition */
  PORT_USI &= ~(1<<PIN_USI_SDA);                    // Force SDA LOW.
  _delay_us( T2_TWI );
  PORT_USI &= ~(1<<PIN_USI_SCL);                    // Pull SCL LOW.
  PORT_USI |= (1<<PIN_USI_SDA);                     // Release SDA.

   /* Write a byte */
  PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
    USIDR = addr+1;// | 0x01;
  USI_TWI_Master_Transfer(tempUSISR_8bit);
  /* Clock and verify (N)ACK from slave */
    DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as 
input.

//////////////////////////////////////////////////////
UND HIER STEIGT ER BEIM 2. AUSLESEN AUS (DER DS1631 sendet kein ACK):
///////////////////////////////////////////////////////
    if( (USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT)) 
)
      error =83;
    else
    {


    //read in MSB
       DDR_USI   &= ~(1<<PIN_USI_SDA);               // Enable SDA as 
input.
       temperature[0]  = USI_TWI_Master_Transfer( tempUSISR_8bit );
    //send ack signal
    USIDR = 0x00; //load ACK
    USI_TWI_Master_Transfer( tempUSISR_1bit );   // Generate ACK


    //read in MSB
       DDR_USI   &= ~(1<<PIN_USI_SDA);               // Enable SDA as 
input.
       temperature[1]  = USI_TWI_Master_Transfer( tempUSISR_8bit );
    //send nack signal
    USIDR = 0xff; //load NACK
    USI_TWI_Master_Transfer( tempUSISR_1bit );   // Generate NACK


    USI_TWI_Master_Stop();
    //temperature conversion

    temperature[0] = (temperature[0] & 0b01111111);

    ret_val = temperature[0] + ((temperature[1]& 0xf0)>>4)*0.0625;





  }

von Christoph R. (christoph63)


Lesenswert?

Das Problem hat sich mittlerweile lösen lassen:
Der Code ist in Ordnung und funktioniert. Das Problem lag an einem 
latenten Kurzschluss am Pullup-Widerstand der SDA Leitung.
Hatte die Möglichkeit mal mit einem Oszi dran zu messen und da viel dann 
sofort auf, dass auf dem SDA nichts los ist.
Was ich seltsam finde ist, dass es von Zeit zu Zeit doch funktioniert 
hat. Evtl. war da noch ein Restwiderstand zur Masse hin vorhanden, der 
sich dann durch Wärmeausdehnung auf der Platine verändert hat.
Sehr seltsam jedenfalls. Ich hätte es eigentlich auch mit dem Multimeter 
feststellen können, bin aber nie drauf gekommen das zu machen weil es ja 
manchmal gefunzt hat. Da hat man nat. als allererstes seinen Code im 
Verdacht.

von Helmut S. (heansch)


Angehängte Dateien:

Lesenswert?

Die Aufgabe, den 2-Byte-Wert des DS1631 in eine vernünftige ASCII 
Anzeige zu wandeln kann Arbeitszeit kosten. Da ich aus den Foren viel 
gelernt habe möchte ich all denen, die zu diesem Thema noch auf der 
Suche sind meinen mittlerweile kurzen Code zur Verfügung stellen. Ich 
hoffe es hilft. Der Code mit Kommentaren ist wie so häufig 
selbsterklärend.
Zum Test der Funktion kann man die Testwerte aus dem Datenblatt 
übergeben.
Die Anzahl der angezeigten Nachkomma-Stellen ist von 0 bis 4 mit 
"DecimalDigits" einstellbar.
Die Funktion "itoa_NoDigits" wandelt nicht nur wie "itoa" sondern fügt 
auch noch das angegebene Füllzeichen vone ein bis die angegebene Anzahl 
von Zeichen erreicht wird. Das ist auch bei allgemeinen Wandlungen für 
LCD Anzeigen "ganz nett".

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
Noch kein Account? Hier anmelden.