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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Peter S. (hainrider)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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:

Bewertung
1 lesenswert
nicht 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)


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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.