Hi, Ich versuche seit stunden einen I2C - Bus per Software zu emulieren. Irgendwie klappt es aber nicht. Ich möchte ein I2C EEPROM Lesen und Schreiben. Kann mit jemand etwas helfen. Gruss und Danke, Schorschi.
seit Stunden?? also, wenn das dann schon funktionieren würde, könntest du dich aber auch schon glücklich schätzen. Wenn du geschreiben hättest "seit Tagen" dann wäre das was anderes. Schreibst du die Tools dafür selber? oder nimmst du fertige?
Flöte ist gar nich mal so abwegig, gibt es zwar nicht mit I2C, aber mit MIDI, was ja auch ein serielles Protokoll ist.
Hi, klar ich sollte ja natürlich auch etwas info geben. Ich verwende nen PIC16LF873A (XTAL 4MHz) und ein 128Bit EEPROM von Microchip und nen C-Kompiler. Der PIC hat zwas nen hardware i2c aber da hab ich die SPI schon für was anderes misbraucht. zu meinem code. Ich habe einige funktionen geschrieben mit denen ich mit übergabe von Adresse und Daten einfach auf das EEprom zugreifen kann. Aber irgendwie funzt das net. hie der code: //------------------------------------------------------------ // pause //------------------------------------------------------------ void pause(void) { SDA=0; SCL=0; } //------------------------------------------------------------ // EEPROM STOP Sequenz //------------------------------------------------------------ void ESTOP(void) { TSCL = 0; TSDA = 0; TSCL = 1; TSDA = 1; } //------------------------------------------------------------ // EEPROM START Sequenz //------------------------------------------------------------ void ESTART(void) { ESTOP(); //Zuerst stop sequenz senden da sonst kein start möglich TSCL = 0; TSDA = 0; } //------------------------------------------------------------ // Schreibe char an EEPROM //------------------------------------------------------------ void WCHAREE(char var) {char u, hvar0=0x80; for(u=0; u<8; u++) { if(var&&(hvar0>>u)) //Bit ist High { TSDA=1; } else //Bit ist low { TSDA=0; } TSCL=1; TSCL=0; pause(); } } //------------------------------------------------------------ // Liest char aus EEPROM //------------------------------------------------------------ char RCHAREE(void) {char o, hvar1=0; TSDA = 1; //Auf eingang schalten for(o=0; o<8; o++) //holen von 8bit { TSCL=1; if(SDA == 1) { hvar1|= 0x01; } TSCL=0; hvar1<<1; pause(); } TSCL=1; TSCL=0; return hvar1; } //------------------------------------------------------------ // EEPROM schreibbefehl //------------------------------------------------------------ char EWRITE(void) { WCHAREE(EWR); //Schreibbefehl senden //Acknowledge TSDA = 1; //Eingang TSCL = 1; //Nächster takt if (SDA == 1) //kein aknowledge { return 0; } else //aknowledge { return 1; } } //------------------------------------------------------------ // EEPROM lesebefehl //------------------------------------------------------------ char EREAD(void) { WCHAREE(ERD); //Schreibbefehl senden //Acknowledge TSDA = 1; //Eingang TSCL = 1; //Nächster takt if (SDA == 1) //kein aknowledge { return 0; } else //aknowledge { return 1; } } //------------------------------------------------------------ // Schreibe EEPROM mit übergabe der Adresse //------------------------------------------------------------ char WEEPROM(char addr, char data) { char ACK=0; ESTART(); //Übertragung Starten ACK = EWRITE();//Schreibbefehl senden if (ACK == 1)//Acknowledge erhalten { WCHAREE(addr); //Adresse an EEPROM Schreiben //Acknowledge TSDA = 1; //Eingang TSCL = 1; //Nächster takt if (SDA == 1) //kein aknowledge { return 2; } else //aknowledge sende daten { WCHAREE(data); //sende daten //Acknowledge TSDA = 1; //Eingang TSCL = 1; //Nächster takt //Acknowledge if(SDA=1) { ESTOP(); //Übertragung beenden return 3;//Kein ack } else { ESTOP(); //Übertragung beenden return 1; //Ack } } } else { ESTOP(); //Übertragung beenden return 4; //Kein ack } } //------------------------------------------------------------ // Lese EEPROM mit übergabe der Adresse //------------------------------------------------------------ char REEPROM(char addr) { char ACK, data; ESTART(); //Übertragung starten ACK=EWRITE();//schreibbefehl if (ACK == 1)//Acknowledge erhalten { WCHAREE(addr+1); //Schreibe zu lesende adresse //Acknowledge TSDA = 1; //Eingang TSCL = 1; //Nächster takt if (SDA == 1) //kein aknowledge { ESTOP(); return 0; } else { ESTART(); //Übertragung starten ACK=EREAD(); //Lesebefehl senden //Acknowledge TSDA = 1; //Eingang TSCL = 1; //Nächster takt if (SDA == 1) //kein aknowledge { ESTOP(); return 0; } else { data = RCHAREE(); ESTOP(); return data; } } } else //keine Acknowledge { ESTOP(); //Übertragung stoppen return 0; } } Mit den Funktionen REEPROM und WEEPROM möchte ich auf das EEprom zugreifen. Danke für eure Hilfe, Gruss Schorschi.
Irgendwie vermisse ich sämtliche Wartezeiten in Deinem Code. Anbei mal meine Routine: http://www.specs.de/users/danni/appl/soft/c51/eeprom/eeprom.c51 Ist zwar für den 8051, aber da es in C ist, kann man es leicht auf den PIC anpassen. Der Hauptunterschied ist, daß beim 8051 die Richtungsumschaltung entfällt, da er bereits open-drain Ausgänge hat. Ich benutze Page-Write und -Read, d.h. es wird ein ganzer Block an Bytes geschrieben bzw. gelesen. Und nach dem Schreiben einer Page erfolgt ein Ready-Polling, um das Schreibende zu erkennen. Für den 24C128 muß auch noch ein Adreßbyte mehr gesendet werden, als für den 24C16. Peter
Hi, danke für eure hilfe aber ich komme da irgendwie nicht weiter. Habe auch schon dass eeprom gewechselt. Daran kann es nicht liegen. ich habe jetzt die funktionen vereinfacht. eifach zeile für zeile programmiert. aber irgendwie funzt es noch nicht. sieht einer von euch da nen fehler drin: //------------------------------------------------------------ // pause //------------------------------------------------------------ void pause(void) { SDA=0; SCK=0; } //------------------------------------------------------------ // Schreibe EEPROM mit übergabe der Adresse //------------------------------------------------------------ void WEEPROM(void) { TSCK=1; // auf eingang schalten TSDA=1; // auf eingang schalten SCK=0; SDA=0; TSDA=0; // start signal pause(); TSCK=0; pause(); TSDA=1; // bit 7 Schreibbefehl pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 6 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 5 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 4 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 3 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 2 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 1 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 0 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // release Data line pause(); TSCK=1; pause(); // hier kommt acknowledge von EEPROM TSCK=0; pause(); // ---------------------------------- TSDA=0; // bit 7 Adresse pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 6 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 5 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 4 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 3 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 2 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 1 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 0 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // release Data line pause(); TSCK=1; pause(); // hier kommt acknowledge von EEPROM TSCK=0; pause(); // ---------------------------------- TSDA=1; // bit 7 DAten pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 6 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 5 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 4 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 3 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 2 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 1 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 0 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // release Data line pause(); TSCK=1; pause(); // hier kommt acknowledge von EEPROM TSCK=0; pause(); // ---------------------------------- TSDA=0; pause(); TSCK=1; pause(); TSCK=0; pause(); TSCK=1; pause(); TSDA=1; // stop condition! } //------------------------------------------------------------ // Lese EEPROM mit übergabe der Adresse //------------------------------------------------------------ char REEPROM(void) { unsigned char result; TSCK=1; // auf eingang schalten TSDA=1; // auf eingang schalten SCK=0; SDA=0; TSDA=0; // start signal pause(); TSCK=0; pause(); TSDA=1; // bit 7 Schreibbefehl pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 6 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 5 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 4 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 3 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 2 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 1 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 0 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // release Data line pause(); TSCK=1; pause(); // hier kommt acknowledge von EEPROM TSCK=0; pause(); // ---------------------------------- TSDA=0; // bit 7 Adresse pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 6 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 5 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 4 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 3 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 2 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 1 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 0 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // release Data line pause(); TSCK=1; pause(); // hier kommt acknowledge von EEPROM TSCK=0; TSCK=1; pause(); TSCK=0; pause(); TSCK=1; pause(); // ---------------------------------- TSDA=0; // repeated start pause(); TSCK=0; pause(); TSDA=1; // bit 7 Lesebefehl pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 6 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 5 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 4 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 3 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 2 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=0; // bit 1 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // bit 0 pause(); TSCK=1; pause(); TSCK=0; pause(); TSDA=1; // release Data line pause(); TSCK=1; pause(); // hier kommt acknowledge von EEPROM TSCK=0; pause(); // ---------------------------------- TSCK=1; if (SDA) result=0b10000000; else result=0; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b01000000; else result=result; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b00100000; else result=result; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b00010000; else result=result; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b00001000; else result=result; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b00000100; else result=result; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b00000010; else result=result; TSCK=0; pause(); TSCK=1; if (SDA) result=result|0b00000001; else result=result; TSCK=0; pause(); TSDA=0; pause(); TSCK=1; pause(); TSCK=0; pause(); TSCK=1; pause(); TSDA=1; // stop condition! return result; } danke und gruss, schorschi.
Kannst Du Dir bitte mal angewöhnen, den Quelltext als Attachment anzuhängen und nicht direkt rein zu kopieren.
Hallo, hat denn keiner nen tip für mich. am oszi sehen die signale richtig aus. soweit ich es interpretieren kann. bitte helft mit ich weiss nicht mehr weiter. gruss und danke, schorschi.
Hast Du schonmal gecheckt, ob nach dem 1. Byte (Adressierung des Chip) auch schon ein Acknowledge kommt? Falls nicht, dann stimmt schon etwas mit der Adresse nicht.
Hi, ein aknowledge hab ich. beim lesen zumidest. aber das schreiben funzt nicht.
Hallo, jetzt habe ich mal wieder zeit gehabt und hab einfach etwas rumprobiert. nun habe ich folgendes problem. wenn ich den startbefehl und daraufhin den lesebefehl sende, bekomme ich ein ACK. wenn ich aber den startbefehl und daraufhin den schreibbefehl sende, bekomme ich kein ACK. Ich verstehe nur nicht warum??? Hat einer da einen Tipp für mich?? Gruss georg.
Hallo, jetzt habe ich zwas ACK's aber wenn ich das eeprom auslese kommt immer noch das gleiche 0xFF raus. Ich kapier garnichts mehr.... Kann denn keiner mir helfen?? gruss und danke, Georg
Hi! Wenn du einen 4Mhz Controller hast dann dürfte doch deine Pausenfunktion void pause(void) { SDA=0; SCL=0; } nur so zwei bis acht Takte brauchen. Der I2C Bus hat aber glaube ich eine maximale Taktrate von 100khz, da kommt dein EEProm nicht so ganz mit. Die beiden Leitungen auf 0 zu setzen brauchst du glaube ich auch nicht. Wie du am besten eine Pause einfügst kann ich dir leider nicht sagen, bis jetzt hab ich den I2C Bus nur per PC & CControl gesteuert, aber so 40-100 nops müssten reichen :-) Viele Grüße Stefan Noll
hi, danke für die antwort. ich habe die pausen auch schon mit ner for - schleife verlängert bringt auch nichts. ich habe ja die ack's aber der ausgelesene bzw. geschriebene wert passt nicht. gruss und danke, Georg.
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.