Forum: Mikrocontroller und Digitale Elektronik Probleme mit MCP9808 über I2C


von Peter S. (hainrider)


Lesenswert?

Hallo euch allen,

ich versuche gerade eine Verbindung zwischen einem Atmega32 und einem 
MCP9808 Temperatursensor über I2C herzustellen. Ich muss leider zu 
geben, dass das meine ersten Gehversuche mit I2C sind.

Ich benutze die Library von Peter Fleury (twimaster.c) und habe das 
Beispiel, welches im Verzeichnis beim Download der Library liegt, als 
Grundlage genommen. Die zwei Leitungen des Buses sind über 4,7kOhm 
Widerstände auf 5V gelegt. Der Atmega32 läuft auf 16 MHz. Laut 
Datenblatt kommuniziert der Sensor mit einer Geschwindigkeit von 100kHz. 
Nun zum eigentlichen Problem. Nach dem Senden der Adresse des Sensors, 
sollte dieser eigentlich ein Acknowledge senden um zu signalisieren, 
dass er da ist. Leider kommt dieser Acknowledge nicht. Drunter habe ich 
euch ein Minimalbeispiel gepostet bei dem der Fehler schon auftritt. Ich 
habe schon verschiedene Lösungen und Sensoren ausprobiert und bin mit 
meinem Latein am Ende. Kann mir jemand bitte sagen, was ich falsch 
mache?

Vielen Dank schon mal ;o)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
#include "uart.c"
#include "i2cmaster.h"

#define MCP9808  0x18      // device address of Temperature sensor 
MCP9808, see datasheet

int main(void)
{
  unsigned char ret;

  uart_init();
  i2c_init();
                                  // init I2C interface
  i2c_start(MCP9808+I2C_WRITE);

  /* write 0x75 to eeprom address 0x05 (Byte Write) */
  ret = i2c_start(MCP9808+I2C_WRITE);       // set device address and 
write mode
  if ( ret ) {
    ///* failed to issue start condition, possibly no device found */
    i2c_stop();
    printf("no device found!");
    }else {
    ///* issuing start condition ok, device accessible */
    i2c_write(0x05);                       // write address = 5
    i2c_write(0x75);                       // ret=0 -> Ok, ret=1 -> no 
ACK
    i2c_stop();                            // set stop conditon = 
release bus
    printf("device found!");
    }
  while(1){}
}

von Uff Basse (Gast)


Lesenswert?

Peter S. schrieb:
> Kann mir jemand bitte sagen, was ich falsch mache?

Du zeigst nicht deinen Schaltplan, der Sensor kann ja ganz
unterschiedlich adressiert sein.

von Bauform B. (bauformb)


Lesenswert?

Peter S. schrieb:
> #define MCP9808  0x18      // device address of Temperature sensor

see datasheet Seite 14

probier mal 0x30
vorausgesetzt, du hast A2 bis A0 auf GND geklemmt, sonst 0x31 bis 0x37

: Bearbeitet durch User
von Peter S. (hainrider)


Lesenswert?

@Bauform B. Du hast Recht. 0x30 hat funktioniert. Ich hatte gedacht 
"0x...." steht für das Hexadezimalsystem. Die 30 kommt allerdings aus 
dem Oktalsystem. Verrückt. Da bin ich in einen richtigen Anfängerfehler 
reingelaufen.

Vielen Dank für deine Hilfe.

von Bauform B. (bauformb)


Angehängte Dateien:

Lesenswert?

Peter S. schrieb:
> @Bauform B. Du hast Recht. 0x30 hat funktioniert. Ich hatte gedacht
> "0x...." steht für das Hexadezimalsystem. Die 30 kommt allerdings aus
> dem Oktalsystem. Verrückt.

In C steht 0x immer für Hex, Oktalzahlen fangen mit 0 an. Man könnte 
auch 48, also Dezimal, schreiben. Entscheidend ist ja, wie die Bits in 
der Hardware ankommen.

Der Unterschied ist, was man unter "I2C-Adresse" versteht. Manchmal 
meint man das komplette Byte, inklusive dem Read/Write-Bit, dann ist 
0x30 richtig. Die eigentliche I2C-Adresse ist 0x18, aber sie ist eben 
nur 7 Bit breit und leider sind es die oberen 7 Bit.

Die Hardware braucht das komplette Byte, also muss das Programm die 
Adresse um ein Bit verschieben. Ob man das wie bei dir gleich im #define 
macht oder ein "<< 1" benutzt oder ob es i2c_start() zur Laufzeit 
erledigt, ist Geschmackssache und jeder macht es anders.

Man könnte auch eine Read-Adresse 0x31 und eine Write-Adresse 0x30 
definieren, aber das sind eben keine Adressen. Offiziell schreibt man 
0x18 und verschiebt irgendwo später.

> Da bin ich in einen richtigen Anfängerfehler reingelaufen.

Das kann man in dem Fall wirklich nicht sagen. Dass Philips die oberen 
und nicht die unteren Bits für die Adresse benutzt hat, hat bestimmt 
schon Millionen Stunden Fehlersuche gekostet.

: Bearbeitet durch User
von Peter S. (hainrider)


Lesenswert?

Okay, das leuchtet mir ein. Vielen, vielen Dank für die Erklärung.

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.