mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik I2C mit software


Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Dom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne, dass du deinen Code hier postest geht das Helfen wohl schlecht.

Dom

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: edi.edi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit einer floete ?,einem pc ?,einem avr ?,einem'51...?

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flöte ist gar nich mal so abwegig, gibt es zwar nicht mit I2C, aber mit
MIDI, was ja auch ein serielles Protokoll ist.

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwie vermisse ich sämtliche Wartezeiten in Deinem Code.

Anbei mal meine Routine:

http://www.specs.de/users/danni/appl/soft/c51/eepr...

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

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst Du Dir bitte mal angewöhnen, den Quelltext als Attachment
anzuhängen und nicht direkt rein zu kopieren.

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohh.

sorry. werde ich in zukunft machen.

danke.

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ein aknowledge hab ich.

beim lesen zumidest.

aber das schreiben funzt nicht.

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Stefan Noll (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Schorschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.