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