2017-06-21 13 views
2

Ich habe eine sehr einfache I2C-Bit-Banging-Bibliothek für ATTINY85.I2C-Sensorwert lesen (Bit-Banging)

Ich kann erfolgreich auf I2C ohne Probleme schreiben. Ich habe diesen Code mit SSD1306 und LC2404B getestet und alles funktioniert gut, sogar die Zeitmessung, wenn VCC auf 4,2 V eingestellt ist.

i2c_init(); 

i2c_start(); 
    i2c_write(0xA0); 
    i2c_write(0x01); 
    i2c_write(0x13); 
i2c_stop(); 

Während Schriftfelter perfekt funktioniert, kann ich nicht in der Lage sein scheinen keine meiner I2C Module mit ATtiny85 auslösen mir einen Wert zurückgeben, die ich später lesen kann.

Ich Himbeere und GY-521 Sensor verbunden (da es Wert zurückgibt, auch wenn interne Adresse nicht eingestellt ist). Ich kann den Sensor erfassen und einen Wert von ihm mit Himbeer die folgende Art und Weise lesen:

i2cdetect -y 1 

    0 1 2 3 4 5 6 7 8 9 a b c d e f 
00:   -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 


i2cget -y 1 0x68 

0x02 

Dies ist die Ausgabe auf dem Oszilloskop ist:

Raspberry I2C output

kann ich die Sensordaten zu ändern sehen. Das Problem ist, ich kann nicht scheinen, die gleiche Anfrage von ATTINY85 auf den Sensor zu replizieren. Der Sensor antwortet einfach nicht mit dem Wert. Ich kann nicht zu verstehen, wenn das letzte Bit im ersten Byte ein ACK oder 'READ' Indikator Bit ist, also habe ich verschiedene Adressen ausprobiert.

i2c_start(); 
i2c_write( 0b11010001); // address: 0xD1 

i2c_start(); 
i2c_write( 0b11010000); // address: 0xD0 

i2c_start(); 
i2c_write( 0b10100001); // address: 0xA1 

i2c_start(); 
i2c_write( 0b10100000); // address: 0xA0 

aber egal auf welcher Adresse ich, der Sensor einfach nicht reagiert (im oscioloscope) und die SDA-Leitung bleibt hoch, nachdem ich den Adress-Byte senden. Ich habe auch versucht, eine andere Start() Bedingung anzufügen, nachdem ich die Adresse gesendet habe, aber immer noch kein Glück. Irgendwelche Hinweise darauf, wo ich falsch liege? Ich möchte einfach den Sensor auf die Leseanforderung ATTINY85 reagieren lassen, damit ich später den Wert lesen kann. Vielen Dank!

Antwort

2

Ich würde vorschlagen, ein paar Tutorials auf I2C zu lesen, um ein allgemeines Verständnis des Protokolls zu bekommen. Siehe zum Beispiel https://learn.sparkfun.com/tutorials/i2c.

Kurz gesagt, I2C ist ein Zwei-Draht-Multi-Master-Bus mit einer Taktleitung und einer Datenleitung. In jeder Kommunikation, ob es ein Lesen oder ein Schreiben ist, liefert der Master das Taktsignal. Ihr i2c_write() implementiert dies mit den SCL-Übergängen.

Um einen Wert zurück zu lesen, müssen Sie auch die Uhr angeben, für die der Slave Daten ausgibt. Keine Uhr, keine Daten. Sie müssen also einen i2c_read() implementieren, der Ihrem i2c-Schreibvorgang ähnelt, der die Taktübergänge erzeugt und jedes Bit einzeln umschaltet.

+0

"Sie müssen auch die Uhr angeben, für die der Slave Daten ausgibt." Das war's! Vielen Dank! – Kristian

2

Sie müssen die SDA-Leitung als Eingang definieren, damit Sie erkennen können, ob der Slave eine ACK sendet oder nicht. Sie haben keinen Code, um die SDA-Leitung als eine Eingabe festzulegen, so dass das Slave-Gerät keine Daten an Sie zurücksenden kann. Der Wert, den Sie auf die SDA-Leitung legen, könnte den Slave überfordern. Und um Daten zurück zu lesen, müssen Sie eine i2c_read Funktion machen, die die SCL-Leitung wackelt, während SDA eine Eingabe ist. Ihre I2C-Implementierung ist daher noch lange nicht abgeschlossen. Sie könnten die I2C spec from NXP sorgfältig lesen oder nach einer vollständigeren bit-hämmernden I2C-Implementierung suchen, um sie als Referenz zu verwenden.

+0

Danke, tolle Quelle! Problem war bei mir, die Uhr nicht an den Slave zurückzugeben. Jetzt kann ich endlich den Wert im Oszilloskop sehen.Das einzige Problem ist, dass der Slave die SDA-Leitung nicht "hart genug" herunterzieht, sondern nur um ~ 50%, aber soweit ich das verstanden habe, sollten Pulldown-/Pullup-Widerstände dies beheben. – Kristian

+1

Wenn du nur die Leitung um 50% herunterziehst, bedeutet das, dass dein Code wahrscheinlich die Leitung hochzieht und der Slave und der Master kämpfen. Wie ich in meiner Antwort gesagt habe, müssen Sie die SDA-Leitung freigeben und zu bestimmten Zeiten eine Eingabe machen, damit der Slave zu Ihnen sprechen kann. –

+0

Vielen Dank für den Hinweis. Obwohl ich meine SDA nicht als Eingabe eingestellt hatte, konnte ich sie seltsamerweise immer noch mit PINB lesen und verglichen mit Oszilloskop-Lesungen schien der Wert übereinzustimmen. Indem Sie es so einstellen, wie Sie es vorgeschlagen haben, haben Sie das 50% -Problem gelöst! – Kristian

Verwandte Themen