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
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; }
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.