Forum: Mikrocontroller und Digitale Elektronik Fleury I2C mit TMP275, Adressierung funktioniert nicht


von Alufolie (Gast)


Lesenswert?

Hallo zusammen,

ich möchte 2 I2C Temperatursensoren (TMP275) gemeinsam auf einem Bus 
betreiben, verwende dabei die Fleury I2C library und bin dabei auf ein 
unerklärliches Problem gestoßen.

Zunächst zum TMP275:
Die I2C Adresse is 1001xxx, für meine Anwendung habe ich die Adressen 
1001000 und 1001001 gewählt (sind geografisch auf der Platine 
festgelegt, bzw. hardcoded).

Als µC verwende ich den ATMega32.

Die Adresse 1001000 lässt sich problemlos ansprechen und die Daten 
kommen richtig an.

Nun zum Problem: Wenn ich jetzt mit dem TMP275 mit der Adresse 1001001 
kommunizieren möchte, fühlt sich dieser nicht angesprochen.
Die Pegel an den Adresspins liegen richtig an und SCL taktet richtig.

ABER die Adresse, die an SDA ausgegeben wird stimmt nicht mit der 
überein, die ich ansprechen möchte. Das an SDA ausgegebene Bitmuster 
stimmt lediglich bei der Adresse 1001000.

Messungen mit dem Oszilloskop über alle möglichen Adressen ergaben 
folgende Bitmuster:

gewünschte Adresse -> Adresse an SDA
1001 000 -> 1001 000
1001 001 -> 1111 010
1001 010 -> 1001 101
1001 011 -> 1111 111
1001 100 -> 1111 000
1001 101 -> 1000 001
1001 110 -> 1101 110
1001 111 -> 1110 011

Hat dieses Problem schonmal jemand erlebt bzw. weiß jemand woran das 
liegen kann?
Ich vermute, dass es entweder am ATMega selbst liegt oder dass es sich 
um ein Problem mit der Fleury library gibt.

Grüße,
Matthias

von Karl H. (kbuchegg)


Lesenswert?

Alufolie schrieb:


> Hat dieses Problem schonmal jemand erlebt bzw. weiß jemand woran das
> liegen kann?

Zeig mal deinen Code.

Dir ist bekannt, dass eine I2C Adresse eine 7-Bit Adresse ist, weil im 
Bit 0 dieses Adressbytes vermerkt wird, ob vom Baustein gelesen oder 
geschrieben werden soll.

d.h. die Frage lautet
Wie will die Routine die Adresse haben? Als 7 Bit rechts aligned und die 
Routine schiebt sich die Adresse selbst um 1 Bit nach links. Oder will 
die Routine das Adressbyte bereits um 1 Bit verschoben haben.

> Ich vermute, dass es entweder am ATMega selbst liegt oder dass es sich
> um ein Problem mit der Fleury library gibt.

Fleury legt das ADressbyte so wie es ist auf den Bus. D.h. die 7_Bit 
Adresse muss von dir bereits so
1
     7   6   5   4   3   2   1   0
2
   +---+---+---+---+---+---+---+---+
3
   |   |   |   |   |   |   |   |   |
4
   +---+---+---+---+---+---+---+---+
5
6
   |                           | ^
7
   +<----- Adresse ----------->| |
8
                                 +-- Bit welches bestimmt ob gelesen oder
9
                                     geschrieben werden soll
in den uint8_t eingebaut sein, den du den Fleury Routinen gibst.

Wobei sich jetzt die nächste Frage ergibt. Wenn im Datenblatt eine 
Hex-Zahl für die Adresse angegeben ist, handelt es sich dabei bereits um 
die um 1 Bit verschobene Version oder muss die angegebene Adresse noch 
um 1 Stelle nach links gerückt werden?
Wenn im Datenblatt eine Adresse angegeben ist, deren 8-Bit 
Repräsentation bereits ein 1 Bit im MSB aufweist, wie zb. 0xD0, dann ist 
die Sache einfach. Denn in 0xD0 ist bereits Bit 7 auf 1 gesetzt, ein 
weiteres Schieben um 1 Position würde daher keinen Sinn machen. 0xD0 ist 
bereits die um 1 Bit verschobene Adresse in die nur noch das 
Richtungsbit eingeodert wird. Anders ist es bei 0x50 mit dem Bitmuster 
0101 0000
Muss dieses Bitmuster so
1
     7   6   5   4   3   2   1   0
2
   +---+---+---+---+---+---+---+---+
3
   | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
4
   +---+---+---+---+---+---+---+---+
eingesetzt werden (und das Richtungsbit überschreibt dann noch Bit 0), 
oder ist das hier
1
     7   6   5   4   3   2   1   0
2
   +---+---+---+---+---+---+---+---+
3
   | 1 | 0 | 1 | 0 | 0 | 0 | 0 |   |
4
   +---+---+---+---+---+---+---+---+
die richtige Lösung und das Richtungsbit kommt noch an die jetzt freie 
Stelle.

Wenn man aus dem Datenblatt hier nicht schlau wird, dann probiert man 
einfach beide Varianten durch, ob eine davon funktioniert.

: Bearbeitet durch User
von Alufolie (Gast)


Lesenswert?

Hallo Karl Heinz,

erstmal danke für deine Antwort.
Was du aber jetzt geschrieben hast bringt mich nicht weiter, da mir das 
alles bewusst ist, ich bin keineswegs ein blutiger Anfänger der null 
Ahnung hat ;).

Na dann, weiter gehts;

Die Adressen werden in 1001xxx angegeben (siehe Datenblatt Seite 8: 
http://www.ti.com/lit/ds/symlink/tmp275.pdf)

Im von mir beschriebenen Problem geht es ums Adressieren und Ansprechen 
des TMP275, also handelt es sich immer um write-Operationen (also 0 
angehängt).

Ich möchte nochmal auf die von mir gemessenen Bitmuster verweisen, die 
am SDA anstelle der gewünschten Adresse ausgegeben werden.

Die Adressen scheinen also falsch ausgegeben zu werden (Ausnahme: 
Adresse 1001000) und deshalb fühlt sich auch kein Sensor angesprochen.

Hier auch noch die entsprechenden Code-Schnipsel:
1
//Definieren der I2C Adressen inkl. r/w-bit
2
#define TMP275_1_w 10010000
3
#define TMP275_1_r 10010001
4
5
//Problem tritt bei dieser Adresse auf
6
#define TMP275_2_w 10010010
7
#define TMP275_2_r 10010011
8
//--------------------
9
10
11
//Sensor 2 konfigurieren
12
//Aus der i2c_start_wait kommt er nicht mehr raus
13
14
15
    i2c_start_wait(TMP275_2_w);     // set device address and write mode
16
    i2c_write(0x1);                       // write pointer register 00000001 to select config register
17
    
18
    i2c_rep_start(TMP275_2_r);    //set device address and read mode
19
    config = i2c_readNak();        //read config register
20
    config |= _BV(6);           //set config register for 12 bit resolution
21
    config |= _BV(5);          
22
    
23
    i2c_rep_start(TMP275_2_w);  // set device address and write mode
24
    i2c_write(0x1);            // write pointer register 00000001 to select config register
25
    i2c_write(config);          // write config back to config register
26
    i2c_stop();
27
28
//--------------------------------
29
30
//definition der i2c_start_wait von fleury
31
//bleibt endlos lange in der while(1) schleife, da Bedingung in
32
// if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
33
//erfüllt ist. twst ist in diesem fall TW_MT_SLA_NACK, die Adresse inkl.
34
//w-bit wird also gesendet, Ack wird aber keins empfangen
35
36
37
void i2c_start_wait(unsigned char address)
38
{
39
    uint8_t   twst;
40
  uint8_t timeout = 1;
41
42
    while ( 1 )
43
    {
44
      // send START condition
45
      TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
46
    
47
      // wait until transmission completed
48
    
49
      while(!(TWCR & (1<<TWINT))); //timeout, damit programm nicht stecken bleibt falls ein temperatursensor ausfällt
50
    
51
      // check value of TWI Status Register. Mask prescaler bits.
52
      twst = TW_STATUS & 0xF8;
53
      if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
54
    
55
      // send device address
56
      TWDR = address;
57
      TWCR = (1<<TWINT) | (1<<TWEN);
58
    
59
      // wail until transmission completed
60
      while(!(TWCR & (1<<TWINT)));
61
    
62
      // check value of TWI Status Register. Mask prescaler bits.
63
      twst = TW_STATUS & 0xF8;
64
65
      if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
66
      {          
67
          /* device busy, send stop condition to terminate write operation */
68
          TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
69
          UDEBUGZ(3);
70
          // wait until stop condition is executed and bus released
71
          while(TWCR & (1<<TWSTO));
72
          
73
          continue;
74
      }
75
    
76
      //if( twst != TW_MT_SLA_ACK) return 1;
77
    
78
      break;
79
    }
80
81
}/* i2c_start_wait */

von Karl H. (kbuchegg)


Lesenswert?

Hö, hö, hö

Das hier
1
#define TMP275_1_w 10010000

ist aber keine Binärzahl.
Das ist die Zahl 10 Millionen 10 Tausend und 0

Für Binärzahlen muss da schon (beim gcc) ein 0b Präfix hin
1
#define TMP275_1_w 0b10010000


(Was wieder mal zeigt: Binärrepräsentierungen sind meistens die dümmste 
Art eine Zahl darzustellen. Man hat einfach zu viele 
Fehlermöglichkeiten. Das reicht vom simplen Verzählen der Bitposition 
über ein vergessenes Bit bis eben zum vergessenen Präfix)

Schreibs doch so
1
#define TMP275_1 0x90
2
#define TMP275_2 0x92
3
4
...
5
6
    i2c_start_wait( TMP275_1 + I2C_WRITE );
7
8
bzw.
9
10
     i2c_start_wait( TMP275_1 + I2C_READ );

dann hast du pro Baustein 1 lesbare Basisadresse und kannst dir auch den 
Kommentar beim start sparen, dass du jetzt lesen bzw. schreiben willst. 
Denn dann steht das im Code selber und nicht im Kommentar

> Die Adressen scheinen also falsch ausgegeben zu werden
Nö. Du hast sie falsch angegeben.

: Bearbeitet durch User
von Alufolie (Gast)


Lesenswert?

Oh mann, jetzt muss ich mich aber schämen für diesen Fehler D:

Oft sind es einfach die simpelsten Dinge, die man dan übersieht.

Die Binär-Darstellung gefällt mir in diesem Fall aber trotzdem besser ;)
Und selbstverständlich ist es mit +I2C_Write/Read übersichtlich, aber da 
ich die Adressen ja mit _w und _r definiert habe läufts auf selbe hinaus 
;)

Vielen Dank jedenfalls für deine Hilfe Karl :) Du konntest den Fehler 
finden, den zwei meiner Professoren und ich nicht finden konnten.

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.