Hab hier nen 24C04 an nem PIC18 im Master-Mode. Device-ID 0xA0 wird an den I2C Teilnehmer gesendet, Ack kommt brav zurück, ich seh's auch aufm Oszi. Gegenprobe: Falsche ID - kein Ack. Hardware ist soweit also ok. Sprut schreibt was von 3mA entsprechend 1,8k für die Pull-Ups, was ich allerdings nicht nachvollziehen kann. Aber egal... mit 2,2k und mit 10k gehts, lediglich die Rise-Zeiten sind unterschiedlich. Das war'S dann aber auch schon. Für das nächste Byte (Adresse für das darauffolgende zu schreibende/lesende Byte) kommt kein Ack mehr. Ich popel jetzt seit über 10h dran rum, langsam gehen mir die Ideen aus. Als Software verwende ich die I2C Libs von Microchip. Habs zwischendurch mal mit nem manuellen Umschalten probiert (PORT RC4 auf dem SDA liegt, auf Eingang geschaltet) weil ich dachte, daß vielleicht das MSSP-Modul des PIC den BUS hoch hält, hat aber nichts gebracht. Hab das Gleiche vor laaanger Zeit mal mit nem 8051 fast auf Anhieb hinbekommen - und jetzt so ne Pleite... Ham die Biester irgendwas spezielles das ich vergessen hab?
Möglicherweise generierst Du eine STOP- oder RESTART-Condition nach dem schreiben der Device-Adresse..? Poste mal die Oszi-Bilder von SCL und SDA
Schade, daß das sich das Rigol im Single-Mode nicht im "großen Fenster" steuern läßt. So halt nur das kleine Bild. Hab zwischendurch noch mit dem WC/Prot-Eingang dws 24C04 rumgespielt, ändert aber nichts. Uups... "unterdrücktes Ack" muß natürlich "bestätigtes Ack" lauten, SDA = low.
Der Zipfel entsteht da der Transistor ja nicht unendlich schnell schaltet. Macht aber nichts, der Zustand wird eh erst während der nächsten High-Periode von SCK geprüft. Da ist die Leitung low.
>Möglicherweise generierst Du eine STOP- oder RESTART-Condition nach dem >schreiben der Device-Adresse..? Hmmm. Eigentlich nicht. #define send 2 #define receive 1 SSPADD = 0x13; // schön langsam... //0A select = send; //select = receive; if (select == send) //send { DeviceSelect = 0b10100000; //1010 + 00 + block number + read /write PIR2bits.BCLIF = 0; // 1. OpenI2C (MASTER,SLEW_OFF); StartI2C(); //2. I2CError = putcI2C(DeviceSelect); // //2a. EEAckError = EEAckPolling(DeviceSelect); //3. I2CError2 = putcI2C(0x30); //beliebigeAdresse //3a. EEAckPollingError2 = EEAckPolling(DeviceSelect); //4. I2CError3 = WriteI2C(0xAA); //Inhalt //4a. EEAckPollingError3 = EEAckPolling(DeviceSelect); StopI2C(); CloseI2C(); }
Das Oszi-Bild hat leider eine etwas schlechte Auflösung, aber die folgende Stelle könnte ein Problem sein: Nach dem ersten Ack gehen CLK und SDA ungefähr gleichzeitig von Low=>High. SDA darf aber nur dann den Pegel wechseln, wen SCL auf LOW ist, ansonsten wird dies als STOP- oder START-Condition interpretiert. Baue mal nach dieser SDA-Flanke etwas Verzögerung bis zur steigenden SCL Flanke ein... http://www.google.ch/url?sa=t&rct=j&q=i2c%20bus%20manual%20nxp&source=web&cd=2&ved=0CDYQFjAB&url=http%3A%2F%2Fwww.nxp.com%2Fdocuments%2Fuser_manual%2FUM10204.pdf&ei=pOJZT6eNLcbP4QTe_5zHDw&usg=AFQjCNG5emVs3tU5RbGVKjblTMFgLLHdqg&cad=rja
Hmmm. Könnte das ne Erklärung dafür sein, daß wenn ich den Baudratenwert SSPADD = 0x13; kleiner mach (schnellerer Takt), der Fehler EEAckError kurioserweise weggeht? Ich hab nämlich laut der Rückgabewerte zwei unterschiedliche Typen Fehler: Bus Collision Error in EEAckpolling und return NACK statt ACK in writeI2C. Weiß jetzt nur noch nicht genau wie ich den an der Stelle langsamer mache...
>Weiß jetzt nur noch nicht genau wie ich den an der Stelle langsamer >mache... => Nur so zum ausprobieren: 100pF an die SCL-Leitung => Als definitive Lösung: Die I2C-Libs fixen oder selber was machen. Frage: Verwendest Du eine Hardware I2C-Bus Schnittstelle auf dem Chip oder ist es eine SW-Emulation des I2C-Buses?
Das I2C im Oszibild ist ja völlig daneben. Dein 2.Paket hat 10 Takte, also einer zuviel. Peter
Ist n alter 18F252 und für den Wiedereinstieg zum üben mit nem 24C04. Später soll dern Slave werden aber der Weg ist noch lang. Ich benutze die Lib für den HW-I2C. Das mit dem Kondensator könnte natürlich sein... den hab ich weggelassen. Irgendwo sah ich mal nen Plan damit und hab mich noch über die zusätzliche kapazitive Last gewundert...
Joachim ... schrieb: > Das mit dem Kondensator könnte natürlich sein... den hab ich > weggelassen. Irgendwo sah ich mal nen Plan damit und hab mich noch über > die zusätzliche kapazitive Last gewundert... Wenn das HW-I2C so einen schweren Bug hat, daß man Kondensatoren braucht, dann sollte man besser SW-I2C machen. Kondensatoren haben am I2C nichts zu suchen! Peter
Uhhh! Peter hat recht. Da ist im Code irgendwas beim Testen durcheinander geraten. Ich dank' euch für die Unterstützung.
Sooo... schreiben funktioniert nun, aber lesen geht noch nicht. Beide Routinen, Lesen und Schreiben sind nahezu gleich, trotzdem verhält sich das vom I2C-Device zurückkommende ACK-bit unterschiedlich. Beim Beschreiben des EEproms kommen alle Ack-bits fehlerfrei, beim Empfangen nur das des ersten Bytes (Packet aus Deviceaddr + Addr high + Addr low + Deviceaddr + Speicherzelle). Wie kann das sein, wenn's beim Lesen und Schreiben die gleichen Routinen sind? Ich hab dieses Phänomen in gleicher Form mit mehreren unterschiedlichen EEproms. Als ob dem Device zum Lesen noch irgendwas fehlt... // Atmel 24C256 = 0b1010000X; //1010 + 0 + address number2 + read /write //I2C-Test write one single Byte and read it #define memAddressInDevice 64 #define valInDevice 11 #define send 2 #define receive 1 //SSPADD = 0x0A;// ca 300kHz SSPADD = 0x28;// ca 95kHz select = send; // Atmel 24C256: if (Taster == 1) select = receive; //pull-up if (select == send) //send { DeviceSelect = 0b10100000; //1010 + 00 + block number + read /write PIR2bits.BCLIF = 0; // 1. OpenI2C (MASTER,SLEW_OFF); StartI2C(); //2. I2CError = WriteI2C(DeviceSelect); // Ziel-Device //3. I2CError2 = WriteI2C(memAddressInDevice); // willkürliche Adresse //3.a I2CError3 = WriteI2C(memAddressInDevice); // willkürliche Adresse2 //4. I2CError4 = WriteI2C(valInDevice); // schreibe Inhalt StopI2C(); CloseI2C(); } // Atmel 24C256: Random Read if (select == receive) //receive, random address read { DeviceSelect = 0b10100001; //1010 + 00 + block number + read /write // 1. OpenI2C (MASTER,SLEW_OFF); StartI2C(); //2. I2CError = WriteI2C(DeviceSelect); //3. I2CError2 = WriteI2C(memAddressInDevice); // willkürliche Adresse //3.a I2CError3 = WriteI2C(memAddressInDevice); // willkürliche Adresse2 //4. I2CError4 = WriteI2C(DeviceSelect); //4. var = ReadI2C(); StopI2C(); CloseI2C(); }
Beim Lesen muss der uC die ACK generieren. Ausnahme, beim letzten Byte gibt es kein ACK, um dem Device anzukündigen, dass nun Schluss ist mit lesen.
Yep hab's mittlerweile hinbekommen, die Abfolgesequenz als solches war nicht vollständig und zum Teil auch falsch. Aber jetzt hab ich n neues, wirklich bizarres Phänomen: Ich hab zwei 18F8F252, einer als Master u. einer als Slave. Der Slave zieht die Taktleitung beim zuschalten des I2C-Moduls, jedoch nicht immer, auf Masse. Auffällig ist, wenn ich auf dem Steckbrett den Draht rausziehe hab ich n EMV-Problem und der Transistoren am Port macht komische Sachen... obwohl der Port auf Eingang geschaltet ist. Als ob er elektrostatische Ladung aufnimmt. Wenn ich kurz mit Masse an den Eingang drüberwische ist der Spuk wieder weg. Hab schon im errata geschaut, diesbezüglich gabs aber nichts. Hab das mit zwei 18F252 ausprobiert, beide haben das gleiche Verhalten.
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.