Forum: PC-Programmierung Linux I2C / SMBUS lesen ohne schreiben


von KMT (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit der I2C Kommunikation zwischen einem 
BananaPi(Lubuntu) und einem Sensor.
Der Sensor schickt mir beim Adressieren + Read-Bit, den aktuellen Wert 
in zwei Bytes verpackt.
(Start)[ADD+R](ACK)[DATA_Byte1](ACK)[DATA_Byte2](Stop)

Nun habe ich mit dem Linuxtreibern für I2C nur die Möglichkeit ein Byte 
als einfache Read-Anfrage abzuholen(READ_BYTE). Es gibt dann noch die 
Funktion "I2C_READ_BLOCKDATA". Mit dieser Funktion kann man bis zu 32 
Byte lesen, jedoch wird vorher noch mittels Write-Sequenz ein 
CMD-Byte(was meist das register ist das man lesen will)  geschickt und 
dann mittel reapeated-start das lesen begonnen. Das dumme daran ist, daß 
der Sensor das repeated start scheinbar nicht mag und nicht wie ich 
gehoft habe einfach die schreib-Sequenz ignoriert.

Hat jemand eine Idee??
Gibt es eine möglichkeit low-level an den I2C-Bus zukommen unter Linux?
Kann man irgendwie den repeated- start unterdrücken (also das ein stop 
zwischen schreiben und lesen gesetzt wird?
bin für alle Ideen und Anregungen dankbar!!!!!!!!!!!!

Vielen Dank im voraus.

Mfg
KMT

von Operator S. (smkr)


Lesenswert?

Schau dir einmal den ioctl Befehl mit den message queue an

http://autotargetingcheerup.googlecode.com/svn-history/r33/trunk/saa7113h/i2c_test.c
Hier ist der wichtige Abschnitt
1
     i2c_data.msgs = msg;
2
        i2c_data.nmsgs = 2;     // two i2c_msg
3
4
        tmp[0] = offset;
5
        i2c_data.msgs[0].addr = saa7113h_ADDR;
6
        i2c_data.msgs[0].flags = 0;     // write
7
        i2c_data.msgs[0].len = 1;       // only one byte
8
        i2c_data.msgs[0].buf = (__u8 *)tmp;
9
10
        /*
11
         * Second, read data from the EEPROM
12
         */
13
        i2c_data.msgs[1].addr = saa7113h_ADDR;
14
        i2c_data.msgs[1].flags = I2C_M_RD;      // read command
15
        i2c_data.msgs[1].len = size;
16
        i2c_data.msgs[1].buf = (__u8 *)data;
17
18
        ret = ioctl(fd, I2C_RDWR, &i2c_data);

von KMT (Gast)


Lesenswert?

Danke erstmal für die Antwort!!!

leider erkenne ich im Quelltext nicht wie ich ansetzen könnte.
Mein Problem ist ja gerade, daß ich ioctl nichts übergeben kann was es 
mir erlaubt mehrere Bytes zu lesen ohne vorher ein write durchzuführen.
So sieht es für mich auch in deinem Quelltext aus... I2C_RDWR steht ja 
für eine kombinerte Schreib-/Lese-Aktion. (repeated start)
Oder kann man die länge der write-Übertragung auch Null setzen und sie 
wird dann einfach nicht ausgeführt.

Kann leider nicht so schnell damit experimentieren da ich im Moment 
mittels Python wrapper draufzugreife. Würde nur gerne wissen ob mein 
Problem überhaupt mit dem linux i2c-dev zu lösen ist ... dann loht es 
sich auch den wrapper und die c-source aufzupimpen.

von Operator S. (smkr)


Lesenswert?

Ein write musst du auf jeden Fall ausführen, um die Daten anzufordern.
In der Zeile
> i2c_data.msgs[1].len = size;
legst du dann fest, wieviele Bytes gelesen werden sollen. In deinem Fall 
müsste size vermutlich 2 sein.

von KMT (Gast)


Lesenswert?

Oh...entschuldigung....mir ist aufgefallen, daß ich nicht deutlich 
gemacht habe was ich meine, als ich geschrieben hab, daß der Sensor kein 
repeated start mag. Das bedeutet in meinem speziellen Fall der Sensor 
auf mein "repeated start read" mit einem NACK antwortet....ich kann ihn 
also so nicht auslösen.
Kommunikation sieht etwas so aus:
(Start)[Add+W](ACK)[Data](ACK)(Start)[Add+R](NACK)(Stop)

habe auch schon alle 256 möglichkeiten für das data-byte durchlaufen 
lassen...ber nach keinem kann ich lesen...kommt immer ein NACK!

von derguteweka (Gast)


Lesenswert?

Moin,

so auf die Schnelle:

1
i2c_data.msgs = msg;
2
        i2c_data.nmsgs = 1;     // one i2c_msg
3
4
        i2c_data.msgs[0].addr = sensor_addr;
5
        i2c_data.msgs[0].flags = I2C_M_RD;      // read command
6
        i2c_data.msgs[0].len = 2;
7
        i2c_data.msgs[0].buf = (__u8 *)data;
8
9
        ret = ioctl(fd, I2C_RDWR, &i2c_data);

Gruss
WK

von KMT (Gast)


Lesenswert?

Hallo,

habe es leider nicht zustande bekommen mit ioctl das I2C device 
anzusprechen...da ich die sach in python umsetze ist die übergabe der 
arg-struct nicht so trivial.

aber ich nutze jetzt die python-lib quick2wire und damit habe ich mein 
problem gelösten.

Vielen Dank!

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.