Mikrocontroller und Digitale Elektronik
›
Thread
I2C mit software
S
Schorschi
Gast
08.06.2004 10:50
#92850
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.
D
Dom
Gast
08.06.2004 15:06
#92851
Ohne, dass du deinen Code hier postest geht das Helfen wohl schlecht.
Dom
SS
Stephan Schwarz
Gast
08.06.2004 15:22
#92852
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?
E
edi.edi
Gast
08.06.2004 15:38
#92853
mit einer floete ?,einem pc ?,einem avr ?,einem'51...?
IH
Ingo Henze
Gast
08.06.2004 15:45
#92854
Flöte ist gar nich mal so abwegig, gibt es zwar nicht mit I2C, aber mit
MIDI, was ja auch ein serielles Protokoll ist.
S
Schorschi
Gast
09.06.2004 14:18
#92855
Hi,
klar ich sollte ja natürlich auch etwas info geben.
Ich verwende nen PIC16LF873 A (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.
PD
Peter D.
(peda)
09.06.2004 14:39
#92856
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
S
Schorschi
Gast
15.06.2004 14:29
#92857
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.
W
Werner
Gast
15.06.2004 14:42
#92858
Kannst Du Dir bitte mal angewöhnen, den Quelltext als Attachment
anzuhängen und nicht direkt rein zu kopieren.
S
Schorschi
Gast
15.06.2004 14:49
#92859
Ohh.
sorry. werde ich in zukunft machen.
danke.
S
Schorschi
Gast
16.06.2004 15:23
#92860
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.
T
thkais
Gast
16.06.2004 18:36
#92861
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.
S
Schorschi
Gast
16.06.2004 18:48
#92862
Hi,
ein aknowledge hab ich.
beim lesen zumidest.
aber das schreiben funzt nicht.
S
Schorschi
Gast
18.06.2004 13:40
#92863
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.
S
Schorschi
Gast
19.06.2004 09:50
#92864
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
SN
Stefan Noll
Gast
20.06.2004 10:51
#92865
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
S
Schorschi
Gast
20.06.2004 12:15
#92866
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.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
Noch kein Account?
Die Registrierung ist kostenlos und dauert nur eine Minute.
Jetzt registrieren