Forum: Mikrocontroller und Digitale Elektronik I²C Problem: verlorene Bytes


von Bob A. (drahtsalat)


Lesenswert?

Guten Tag,

erstmal Sorry für den ungenauen Thread-Titel, aber es ist etwas schwer 
zu schildern, was man wohl auch an der Textlänge erkenne kann...

Ich hab hier ein Projekt mit einem PCA9564  I²C Host Controller an einem 
Motorola MC68VZ328 µC.
Es hängt etliches an I²C Peripherie dran, auch ein paar EPROMs. Der Bus 
wird mit einem PCA9548 eines noch in weitere "Sub-Busse" aufgeteilt.
Ich habe das Projekt von einem Kollegen übernommen, der jetzt leider 
nicht mehr in der Firma ist. Schaltung und Software sind nicht von mir, 
was es für mich nicht einfacher macht mich reinzudenken.
Nun habe ich eine Erweiterung vor bei der ich die bisherige Ansteuerung 
der EPROMs verändern muss. Daten werden bisher nur Byte-weise 
ausgelesen. Das frisst jede Menge Zeit wenn die komplette Kommunikation 
jedes mal neu aufgebaut und neu adressiert wird.
Die EPROMs können sequentiell ausgelesen werden, das funktioniert aber 
nicht zu 100% so wie es soll.

Will ich 3 Bytes ab Adresse 0 auslesen erhalte ich zurück Bytes 1 2 und 
3. Ein anschliessendes Auslesen fördert dann die Bytes 5 6 und 7 zutage.
Am Oszi hgabe ich auch beobachtet dass die Bytes am Bus erscheinen, aber 
wohl nicht von der Software ausgelesen werden.
Um's komplett kompliziert zu machen: Das Auslesen eines einzelnen bytes 
funktioniert einwandfrei.

Dann habe ich in der do-Schleife den Aufruf von ResetSI() hinter das 
auslesen der Daten aus dem PCA9564-Register (*data = 
ReadI2CHostRegister(HostData) & 0xff;) geschoben.
Nun erhlate ich die Bytes 0, 1 und 3. 2 wird "übersprungen". 
Anschliessend kommt dann 4, 5 und 7.

Dem Code entnehme ich, dass Aktivität auf der Taktleitung nur ausgelöst 
wird wenn das SI-bit zurückgesetzt ist. Dafür habe ich im Datenblatt 
aber noch keine Bestätigung gefunden :/
Irgendwas sorgt aber vorher schon dafür dass auf SCL Takte ausgegeben 
werden.
Deswegen ist auch schon ein Byte vorhanden wenn ich in die Schleife 
springe.

Ich hab das bis jetzt so verstanden:
Irgend ein Befehl lässt SCL tackern bevor die do-Schleife erreicht wird, 
und auch vor dem letzten auszulesenden Byte werden Takte ausgegeben ohne 
dass das Register ausgelesen wird.

Im Moment bin ich wohl etwas betriebsblind und weiss nicht mehr wo 
weitersuchen...
Vielleicht hat ja hier jemand eine Idee wo ich noch draufschauen 
könnte...
Bin für jeden Hinweis dankbar!

hier die Auslese-Funktion (schon so geändert wie beschriebe, dass 0 1 
und 3 ausgelesen werden)
1
void I2CRead (unsigned char baustein,
2
    unsigned char *data,
3
    unsigned long Anzahl_Daten,
4
    unsigned int *Abbruch,
5
    unsigned char *I2CSTAT)
6
{
7
  unsigned long Daten/*, d[100]*/;
8
  // Initialisieren
9
  Daten = 0;
10
  *Abbruch = 0;
11
  // Lesen aktivieren
12
  baustein += 1;
13
  // Startbedingung
14
  I2CInit ();
15
  // Status erfragen
16
  *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
17
  // Startbedingung erfolgreich?
18
  if ((*I2CSTAT != 0x08) & (*I2CSTAT != 0x10))
19
  {
20
    // Nö, Stop Bedingung auf Bus
21
22
    WriteI2CHostRegister (HostControl, 0xff50);
23
    // übertragen
24
    ResetSI ();
25
    // Abbruch
26
    return;
27
  }
28
  // Fehlerzähler auf nächste Stufe
29
  *Abbruch += 1;
30
  // Baustein adressieren und auf Lesen vorbereiten
31
  WriteI2CHostRegister(HostData, (unsigned short)baustein | 0xff00);
32
  // übertragen
33
  ResetSI ();
34
35
  // Status erfragen
36
  *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
37
  // Ist der Baustein da?
38
  if ((*I2CSTAT != 0x40) & (*I2CSTAT != 0x50))
39
  {
40
    // Nö, Bus Stop
41
    WriteI2CHostRegister (HostControl, 0xff50);
42
    // übertragen
43
    ResetSI ();
44
    // Abbruch
45
    return;
46
  }
47
  // Fehlerstufe eins hoch
48
  *Abbruch += 1;
49
  // Werden mehr Daten gelesen muss Acknowledged werden
50
  if (Anzahl_Daten > 1)
51
    EnableAck ();
52
  // Fertig machen zum Lesen der Daten
53
  do
54
  {
55
    // Status erfragen
56
    *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
57
    // x-tes Byte in den Empfangsspeicher
58
    *data = ReadI2CHostRegister(HostData) & 0xff;
59
    // nächstes Byte abholen
60
    ResetSI ();
61
62
    // x-tes Datenbyte empfangen?
63
    if ((Daten < Anzahl_Daten - 1) && (*I2CSTAT != 0x50))
64
    {
65
      // nein, Bus Stop
66
      WriteI2CHostRegister (HostControl, 0xff50);
67
      // senden
68
      ResetSI ();
69
      return;
70
    }
71
    // letztes Datenbyte empfangen?
72
    if ((Daten == Anzahl_Daten - 1) && (*I2CSTAT != 0x58))
73
    {
74
      // ja, Bus Stop
75
      WriteI2CHostRegister (HostControl, 0xff50);
76
      // senden
77
      ResetSI ();
78
      return;
79
    }
80
    // vorletztes Datenbyte empfangen?
81
    if (Daten == Anzahl_Daten - 2)
82
    {
83
      // dann Acknowledge aus
84
      DisableAck ();
85
    }
86
    // Fehlerstufe weiter
87
    *Abbruch += 1;
88
    // nächster Datensatz
89
    data++;
90
    // Datenzähler weiter
91
    Daten++;
92
    writew(0x1, WATCHDOG);
93
    // bis alle Daten gesendet sind
94
  } while (Daten < Anzahl_Daten);
95
  // Stop Bedingug einleiten
96
  WriteI2CHostRegister (HostControl, 0xff50);
97
  // senden
98
  ResetSI ();
99
  // Status abfragen
100
  *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
101
  //  return I2CSTAT;
102
}

von Spitzbube (Gast)


Lesenswert?

Ich wuerd mal aufzeichen welche Sequenz da sein sollte, und dann mit dem 
Analyzer nachmessen, ob das auch so ist.

Und das sequentiell fuer jedes Bauteil am Bus.

von Bob A. (drahtsalat)


Lesenswert?

Analyzer hab ich keinen, leider!

Aber das was ich am Oszi sehe ist eigentlich korrekt, bis auf die 
Tatsache dass ein Byte zu viel auf dem Bus erscheint.
Das vorletzte Byte wird aber von der Software nicht erfasst.

von Jörg S. (joerg-s)


Lesenswert?

Bob A. schrieb:
> Aber das was ich am Oszi sehe ist eigentlich korrekt, bis auf die
> Tatsache dass ein Byte zu viel auf dem Bus erscheint.
Und das Byte erscheint weil Takte kommen die du nicht ausgelöst hast?



>Dann habe ich in der do-Schleife den Aufruf von ResetSI() hinter das
>auslesen der Daten aus dem PCA9564-Register (*data =
>ReadI2CHostRegister(HostData) & 0xff;) geschoben.
Warum? Die I2CRead() Funktion wird doch auch erfolgreich zum lesen 
anderer Bausteine verwendet, oder nur beim EEPROM?

Und was ist mit I2CWrite()? Wenn du 3 Byte lesen willst, musst du doch 
erst mal 1 Byte schreiben (Speicheradresse). Anschliessend (mit Repeated 
Start oder kompletter neustart) musst du 3 Byte lesen.

von Bob A. (drahtsalat)


Lesenswert?

Jörg S. schrieb:
> Bob A. schrieb:
>> Aber das was ich am Oszi sehe ist eigentlich korrekt, bis auf die
>> Tatsache dass ein Byte zu viel auf dem Bus erscheint.
> Und das Byte erscheint weil Takte kommen die du nicht ausgelöst hast?

Genau so stellt sich das im Moment für mich dar. D.h. irgendwo werden 
die Takte wohl ausgelöst werden, ich sehe nur gerade nicht wo :/


>>Dann habe ich in der do-Schleife den Aufruf von ResetSI() hinter das
>>auslesen der Daten aus dem PCA9564-Register (*data =
>>ReadI2CHostRegister(HostData) & 0xff;) geschoben.
> Warum? Die I2CRead() Funktion wird doch auch erfolgreich zum lesen
> anderer Bausteine verwendet, oder nur beim EEPROM?

Die Software war eben so gestrickt, dass immer nur ein einzelnes Byte 
gelesen wurde. Dann Bus Stopp, neu adressiert und nächstes Byte. 
Ziemlich ineffektiv bei mehreren kByte... deswegen möchte ich das ja 
ändern.

> Und was ist mit I2CWrite()? Wenn du 3 Byte lesen willst, musst du doch
> erst mal 1 Byte schreiben (Speicheradresse). Anschliessend (mit Repeated
> Start oder kompletter neustart) musst du 3 Byte lesen.

Stimmt, das funktioniert scheinbar, aber auch hier werden immer nur 
einzelne Bytes geschrieben. Weiter getestet hab ich das noch nicht, ich 
möchte zuerst mal das Lesen korrekt hinkriegen, danach schau ich mir das 
Speichern an. Sollte hier auch ein Problem sein, hoffe ich dass die 
gleiche Lösung greift...

von Jörg S. (joerg-s)


Lesenswert?

Bob A. schrieb:
> Die Software war eben so gestrickt, dass immer nur ein einzelnes Byte
> gelesen wurde. Dann Bus Stopp, neu adressiert und nächstes Byte.
> Ziemlich ineffektiv bei mehreren kByte...
Ja, aber wurde denn bei ALLEN I2C Bausteinen immer nur 1 Byte gelesen?

>> Und was ist mit I2CWrite()? Wenn du 3 Byte lesen willst, musst du doch
>> erst mal 1 Byte schreiben (Speicheradresse). Anschliessend (mit Repeated
>> Start oder kompletter neustart) musst du 3 Byte lesen.
> Stimmt, das funktioniert scheinbar, aber auch hier werden immer nur
> einzelne Bytes geschrieben.
Na ja, für die Chip-Adresse und die nachfolgende Speicheradresse sind es 
schon mal 2 Bytes auf dem Bus.

> Weiter getestet hab ich das noch nicht, ich
> möchte zuerst mal das Lesen korrekt hinkriegen, danach schau ich mir das
> Speichern an.
Also wenn ich das richtig verstehe sendest du erst mal keine 
Speicheradresse, sondern willst nur 3 Byte lesen? Oben schreibst du doch 
aber das du ab Adresse 0 was lesen willst?

von Bob A. (Gast)


Lesenswert?

Hmm, ja hab mich unklar ausgedrückt, sorry.

Beim schreiben sind es in der Tat zwei Bytes, sogar 3 wenn man es genau 
nimmt, denn es sind beim EEPROM 16-bit Adressen.

Die Software ist komplett so gehalten dass immer nur 1 Byte ausgelesen 
wurde. Vielleicht hatte der Entwickler damals das gleiche Problem und 
hat es damit umgangen, dass er immer alle Bytes einzeln eingelesen hat, 
wer weiss das schon??

Ich sende schon die Adresse, danach lese ich immer 3 Bytes. Nach der 
Adressierung sind das die Bytes an Adresse 0, 1 und 3. Da die Software 
wohl eins überspringt.
Danach steht der Adress-pointer auf Speicherzelle 4, ich lese dann 4, 5 
und 7 u.s.w.

Ich bin nicht mehr im Büro, deswegen kann ich jetzt nicht nachprüfen wie 
es beim Senden ausschaut.
Montag versuch ich das mal genauer zu inspizieren!

Vielen Dank erstmal an und schönes WE

von holger (Gast)


Lesenswert?

Bei sowas bin ich ja immer etwas paranoid:

    if ((Daten < Anzahl_Daten - 1)
    if ((Daten == Anzahl_Daten - 1)

Lieber mal ein paar Klammern zu viel als zu wenig:

    if ((Daten < (Anzahl_Daten - 1))
    if ((Daten == (Anzahl_Daten - 1))

von holger (Gast)


Lesenswert?

Ich würde auch erst mal die Schleife aufräumen. Da steht viel zu viel 
drin.
1
  // Werden mehr Daten gelesen muss Acknowledged werden
2
  if (Anzahl_Daten > 1)
3
    EnableAck ();
4
5
  uint16_t len = Anzahl_Daten;
6
  
7
  // Schleife für alle Daten mit Acknowledge
8
  while(len - 1)
9
  {
10
    // Status erfragen
11
    *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
12
    // x-tes Byte in den Empfangsspeicher
13
    *data++ = ReadI2CHostRegister(HostData) & 0xff;
14
    // nächstes Byte abholen
15
    ResetSI ();
16
17
    // x-tes Datenbyte empfangen?
18
    if ((*I2CSTAT != 0x50))
19
    {
20
      // nein, Bus Stop
21
      WriteI2CHostRegister (HostControl, 0xff50);
22
      // senden
23
      ResetSI ();
24
      return;
25
    }
26
27
    // Fehlerstufe weiter
28
    *Abbruch += 1;
29
30
    writew(0x1, WATCHDOG);
31
32
    // bis alle Daten gesendet sind
33
    len--;
34
  }
35
36
  // letztes Byte ohne Acknowledge
37
  DisableAck ();
38
39
  // Status erfragen
40
  *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
41
  // x-tes Byte in den Empfangsspeicher
42
  *data = ReadI2CHostRegister(HostData) & 0xff;
43
44
  // Stop Bedingug einleiten
45
  WriteI2CHostRegister (HostControl, 0xff50);
46
  // senden
47
  ResetSI ();
48
  // Status abfragen
49
  *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;
50
  //  return I2CSTAT;

von holger (Gast)


Lesenswert?

Nachtrag: Da bleibt aber immer noch ein übler Nachgeschmack.
In deinem Code ist nicht ersichtlich wer wann die Datenübertragung
auslöst. EnableAck() oder DisableAck() sollte man nicht
während des Transfers machen, sondern vorher.

von Bob A. (drahtsalat)


Lesenswert?

holger schrieb:
> EnableAck() oder DisableAck() sollte man nicht
> während des Transfers machen, sondern vorher.

Die beiden hab ich mittlerweile auch im Verdacht... aber wie kann ich 
dann gewährleisten dass das letzte gelesene Byte nicht acknowledged 
wird?
Oder ist das nicht zwingend notwendig? Bisher hab ich das immer so in 
den Datenblättern gelesen.

P.S. da ein Kollege gerade das Oszi braucht ist erstmal Pause mit 
Debugging :/

von Jörg S. (joerg-s)


Lesenswert?

Bob A. schrieb:
> Ich sende schon die Adresse, danach lese ich immer 3 Bytes. Nach der
> Adressierung sind das die Bytes an Adresse 0, 1 und 3. Da die Software
> wohl eins überspringt.
> Danach steht der Adress-pointer auf Speicherzelle 4, ich lese dann 4, 5
> und 7 u.s.w.
Leider wird dadurch nicht klarer was du machst.
Wieso holst du 2x 3 Byte, warum nicht auf einen Schlag 6 Byte?
Gibt es zwischen schreiben der Adresse und lesen der Bytes ein Stop oder 
ein Repeated Start?
Gibt es zwischen dem lesen der ersten 3 Bytes und den letzten 3 Bytes 
ein Repeated Start?


Das übliche (schnellste) vorgehen wäre ja
- Start,
- Chip Adresse mit Write Bit senden
- 2 Byte Speicheradresse senden
- Repeated Start
- Chip Adresse mit Read Bit senden
- 6 Byte aus EEPROM lesen (beim letzten Byte NACK senden)
- Stop

von Bob A. (drahtsalat)


Lesenswert?

Stimmt schon, dass es wenig Sinn mach die Daten stückchenweise 
auszulesen.

Die 2 x 3 Byte sind ein simpler Test um zu verstehen was da eigentlich 
passiert.

Ich hatte das Problem dass beim Lesen mehrere Byte in Folge als erstes 
Byte immer (Adresse + 1) ausgelesen wurde.

Durch Ändern der Reihenfolge von
1
*data++ = ReadI2CHostRegister(HostData) & 0xff;
und
1
ResetSI ();
war dieses Problem beseitigt.

Dafür hatte ich mir eine kleine Testschleife gebaut die ohne erneute 
Adressierung immer 3 Byte am Stück ausliest.

Hierbei ist mir dann aufgefallen, dass am Schluss auch noch mal Takte 
generiert werden, und dann am Ende ein Byte verschluckt wird.
Das ist ja unabhängig davon ob ich 6 am Stück oder 2 mal 3 Byte lese.

(Eigentlich lese ich unendlich viele 3-Byte Pakete... Das Ganze ist, wie 
gesagt, nur ein Testaufbau.)

von Bob A. (drahtsalat)


Lesenswert?

Ich hab das jetzt mal in Anlehnung an holgers Vorschlag umgebaut... 
leider keine Veränderung.

Kann es sein dass das Ein-/Ausschalten vom Acknowledge Takte generiert?
Im Datenblatt habe ich dazu nichts gelesen...

Hat hier schon jemand den PCA9564 benutzt und weiss was genaueres?

Gruß und Dank,
Bob

von Stampede (Gast)


Lesenswert?

Ohne jetzt alle Beiträge gelesen zu haben: Das ist 100% ein Problem mit 
dem ACK. Nach dem Commando fürs Lesen wird das ACK vom Slave gesendet. 
Die nachfolgenden Bytes, die du liest, musst du (sprich der Master) mit 
einem ACK quittieren. Nur das letzte Byte erhält KEINEN ACK.

von Peter D. (peda)


Lesenswert?

Bob A. schrieb:
> WriteI2CHostRegister (HostControl, 0xff50);
>   // senden
>   ResetSI ();
>   // Status abfragen
>   *I2CSTAT = ReadI2CHostRegister(HostStatus) & 0xff;

Ohne zu wissen, was diese magischen Funktionen mit den magischen 
Parametern konkret machen, kann man dazu nichts sagen.
Das ist nur Stochern im Nebel.
Man bräuchte die komplette I2C-API-Beschreibung.

Einfacher wird es, wenn man sich Macros schreibt, die wie die benötigten 
I2C-Funktionen heißen:

send_start()
send_byte_read_ack()
read_byte_with_ack()
read_byte_with_nack()
send_stop()

Damit kann man viel besser das Programm lesen und nachvollziehen.


Peter

von Andreas H. (Gast)


Lesenswert?

Bob A. schrieb:
> // x-tes Datenbyte empfangen?
>     if ((Daten < Anzahl_Daten - 1) && (*I2CSTAT != 0x50))
>     {

...

>     if ((Daten == Anzahl_Daten - 1) && (*I2CSTAT != 0x58))
>     {
>       // ja, Bus Stop

Müsste das nicht jeweils "*I2CSTAT ==" sein ?

Du erwartest ja eigentlich 0x50 (aka. received and acked), bzw 0x58 
(aka. received and not acked) beim letzten byte. Prüfen tust Du aber auf 
UNGLEICH.

In Deinem Code sieht das so aus, als ob Deine Routine dort einfach 
weiter läuft.

Grüße
Andreas

von Bob A. (Gast)


Lesenswert?

@Andreas:

Nee, das ist schon richtig so,

wenn der Status ungleich ist geht's in die Schleife und dann wird 
abgebrochen. In der übergeordneten Funktion kommt dann die 
Fehlerbehnadlung.

@Peter:
die magischen Funktionen bedienen den PCA9564.
Mit so spezifische Funktionen kann ich leider nicht dienen. Ob ACK oder 
nicth z.Bsp. ist eine Konfigurationssache beim PCA9564. Vor dem Lesen 
des letzten Bytes wird das entsprechende Bit im PCA9564 gesetzt.

Den magischen Source-Code kann ich leider erst Morgen liefern...

Vielen Dank für die Hilfe und ganzen Anregungen hier!!
Bob

von Jörg S. (joerg-s)


Lesenswert?

Ich würde einfach erst mal nur 2 Byte vom EEPROM lesen, ohne Write 
zugriff vorher. Damit schliesst man schon mal Fehler an dem Teil aus.
Und dann mal ganz genau mit dem Oszi schauen was da so auf dem Bus genau 
passiert. Evt. dazu einen Pin vom µC als Debug Pin konfigurieren und zum 
triggern des Oszi benutzen um zu sehen was wann passiert.

von Bob A. (drahtsalat)


Lesenswert?

@Jörg:
aber genau das mache ich ja, deswegen kam ja erst diese Verwirrung mit 
wieso nicht 6 anstatt 2 mal 3. Ich lese halt in einer Schleife immer 
fortlaufend...

Bleiben wir mal bei den 3 Bytes die ich auslese:
Start condition ist OK
dann kommt die Adresse vom EEPROM und ACK von eben diesem
dann 2 Bytes mit ACK vom PCA9564
das dritte und eigenltich letzte Byte kriegt dann wieder ein ACK obwohl 
es nicht sollte
das 4. Byte bekommt dann aber kein ACK
Stop condition

Die eingelesenen Daten zeigen mir dann dass das dritte Byte 
"verschluckt" wurde und ich habe den Inhalt von Byte 1 2 und 4.

Sieht am  Oszi eigentlich alles so aus wie es sich gehört, auffällig ist 
bloss, dass das 4 Byte zeitlich deutlich schneller hinter dem 3. kommt 
als dies der Fall bei den anderen Transfers ist. Zwischen Adresse und 
Daten und auch zwischen den Daten habe ich grob die gleiche Zeit.
Das gilt auch bei mehr als 3 Byte, das letzte kommt immer deutlich 
kürzer hinter dem Vorletzten als alle vorherigen.

von Wolfgang R. (eg61ejub)


Lesenswert?

Bei meinem barometer (BMP085) gibt's ein ähnliches Problem.

Ich lese 2 Bytes für die Temperatur aus und anschließend 3 für den 
Druck.
Die Bytes speicher ich einfach auf eine SD-Karte im csv.Format.

So sollte es sein:

 MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, XLSB-Druck, \n
 MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, XLSB-Druck, \n
 MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, XLSB-Druck, \n
 MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, XLSB-Druck, \n
 MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, XLSB-Druck, \n
...

Und so ist es:

 MSB-Temp, LSB-Temp,        0, MSB-Druck, LSB-Druck, \n
XLSB-Temp, MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, \n
XLSB-Temp, MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, \n
XLSB-Temp, MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, \n
XLSB-Temp, MSB-Temp, LSB-Temp, MSB-Druck, LSB-Druck, \n
...

Ein einziges mal wird diese Null mitgesendet. Wenn ich am Code etwas 
rumstelle kann auch statt der 0 eine 165 an Stelle vom XLSB-Temp stehen.
Deswegen einmal @Bob: Vielleicht verlierst du garnicht dein Byte, 
sondern liest drei Bytes aus nachdem du die Adresse schreibst und eins 
ist fehlerhaft oder einfach 0 und wird dadurch in deiner Datei oder wo 
du es auch immer abspeichert nicht abgespeichert.
@Alle: Woher kommt diese einmalige 0???

von Bob A. (drahtsalat)


Lesenswert?

@Wolfgang:

nee das Byte ist schon da ich sehe es ja am Oszi, dort kommen nach der 
Adressierung ganz klar 4 mal Takte und der Inhalt der 4 Speicherzellen.

Woher deine 0 kommt? Kein Plan! Pollst du oder ist die I²C Routine 
interrupt-gesteuert. Beim Pollen könnte es eventuell ein timeout sein...
Immer hilfreich: Oszi oder Logic-analyzer dranhängen und kucken was da 
wirklich abgeht!

Viel Erfolg bei der Suche,
Bob

von Wolfgang R. (eg61ejub)


Lesenswert?

@Bob:
Hier ist die Lösung für mein Problem. Vielleicht liegt es bei dir ja an 
etwas ähnlichem.

Der Fehler lag im Auslesen des Multireads.

So hatte ich es:
write()
wait()
start_read()
MSB = get_value()
LSB = get_value()
stop_read()

So soll es sein:
write()
wait()
start_read()
MSB = get_value()
stop_read()
LSB = get_value()

Nach dem "Stop-Generieren" wird vom Slave also vom Barometer noch ein
Byte gesendet. Deswegen muss der Stop vor dem letzten Byte, das man
auslesen möchte, gesendet werden.

Grüße

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.