www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 24LC128 EEPROM auslesen


Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich bin gerade dabei ein I2C EEPROM (24LC128) anzusteuern. Wenn ich das 
EEPROM mit Daten beschreiben will, muss ich ja die Pagegröße beachten. 
Außerdem muss ich beachten ab welcher Adresse ich anfange mit schreiben.
Wollte jetzt mal nachfragen ob ich beim Auslesen (Sequential read) auch 
die Pagegröße beachten muss. Also ob ich maximal 64bytes auf einmal 
auslesen kann. So wie ich das Datenblatt lese, bin ich der Meinung ich 
kann so lange auslesen bis der Master "kein ACK" sendet.
Könnt ihr mir da weiter helfen?

Grüße

Bean

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Mr Bean (Gast)

>Wollte jetzt mal nachfragen ob ich beim Auslesen (Sequential read) auch
>die Pagegröße beachten muss.

Nein, man kann ohne Begrenzung auslesen.

>kann so lange auslesen bis der Master "kein ACK" sendet.

Ja.

MFG
Falk

Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, sehr gut. Das lesen aus dem EEPROM scheint jetzt auch zu 
funktionieren. Nur das Schreiben über Pagegrenzen hinweg macht mir noch 
etwas Probleme. (Schreiben einzelner Bytes funktioniert)
Habt ihr mir hier vielleicht noch irgend einen Tipp?

Grüße

Bean

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Mr Bean (Gast)

>funktionieren. Nur das Schreiben über Pagegrenzen hinweg macht mir noch
>etwas Probleme.

Das muss man aufteilen. Man kann immer nur innerhalb einer Page 
schreiben.

Mfg
Falk

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Habt ihr mir hier vielleicht noch irgend einen Tipp?
Berechnen, ob ne Page überschritten wird. Entsprechend Schreibvorgang 
für die aktuelle Page beenden und für die neue Page starten.

Ralf

Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das hab ich mir auch schon überlegt, aber dazu muss ich ja erstmal 
berechnen wieviel bytes ich in die angefangene Page (wenn ich mitten im 
Speicher anfange mit schreiben) noch schreiben kann. Dann muss ich noch 
berechnen wie viele Pages ich überschreib und dann dementsprechend die 
Adressen setzen und die Pages voll schreiben oder sehe ich das falsch? 
Vielleicht denke ich auch zu kompliziert.
Habt ihr mir speziell hierzu vielleicht noch BSP Code. Habe bis jetzt 
immer nur das Schreiben einzelner Bytes... gefunden. Kein "Streams".
Grüße

Bean

Und danke schonmal!

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Mr Bean (Gast)

>Ja, das hab ich mir auch schon überlegt, aber dazu muss ich ja erstmal
>berechnen wieviel bytes ich in die angefangene Page (wenn ich mitten im
>Speicher anfange mit schreiben) noch schreiben kann. Dann muss ich noch
>berechnen wie viele Pages ich überschreib und dann dementsprechend die
>Adressen setzen und die Pages voll schreiben oder sehe ich das falsch?

Das siehst du richtig. Iast aber nicht so kompliziert. Der Modulo 
Operator ist dein Freund.

Adresse MOD Pagesize = Page_Position

Pagesize - Page_position = Anzahl Bytes in der 1. Page

MfG
Falk

Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, soetwas hab ich mir schon gedacht. Scheitere aber gerade daran wie 
ich weiter mache wenn ich die erste Page voll geschrieben hab. Hier mal 
mein derzeitiger Code:
int EEPROM_BUF_Write(unsigned int address, unsigned char buf[], unsigned int count)
{
  unsigned char retval;
  unsigned char I2Cstat;
  unsigned char sendbuf[PAGESIZE];
  unsigned char i=0;
  unsigned int pos = 0;
  unsigned char bytenum = 0;

  sendbuf[1] = address & 0xFF;
  sendbuf[0] = (address >> 8) & 0xFF;
  
  if(count > PAGESIZE)
  {
    pos = address % PAGESIZE;
    bytenum = PAGESIZE - pos;
    
    SMB_Write(EEPROM_ADDR, sendbuf, 2);
  
    while(i <= bytenum)
    {
      SMB_Write(EEPROM_ADDR, buf, bytenum);
      count--;
      address++;
      i++;
    }
    sendbuf[1] = address & 0xFF;
    sendbuf[0] = (address >> 8) & 0xFF;
    SMB_Write(EEPROM_ADDR, sendbuf, 2);

  }
  
  else
  {
    SMB_Write(EEPROM_ADDR, sendbuf, 2);
    I2Cstat = SMB_Write(EEPROM_ADDR, buf, count);
    if(I2Cstat)
    {
      retval = EEPROMWRITEFAIL;
    }
    retval = EEPROMWRITESUCCESS;
  }
  return retval; 
}

Ist aber wie gesagt noch nicht fertig. Ich meiner SMB_Write funktion 
sagen soll dass Sie wenn ich die nächste Page beschreiben will bei 
meinem Datenbuffer (buf[]) wieder an Stelle null anfängt... :-(

Grüße

Bean

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denke auch daran, dass Du nach dem schreiben einer Page einige 
Millisekunden warten musst (siehe Datenblatt), bis Du wieder auf's 
EEPROM zugreifen kannst...

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ACK polling ist hier auch besser als delay_ms ^^
ack polling bis wieder frei ist dann weiterschreiben

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine variable kannst du noch einsparen

statt
  unsigned int pos = 0;
  unsigned char bytenum = 0;


    pos = address % PAGESIZE;
    bytenum = PAGESIZE - pos;



gehts auch gleich

  unsigned char bytenum = 0;


    bytenum = PAGESIZE - (address % PAGESIZE);

das pos is umsonst

Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja stimmt, dachte ich brauche "pos" später noch...
Ich hatte mir soetwas mit dem ACK schon gedacht. Bin mir aber nicht 
sicher ob das bei meinem Baustein funktioniert, im Datenblatt steht:

"The 24XX128 does not generate any
Acknowledge bits if an internal
programming cycle is in progress."

Ich hab jetzt mal 5ms warten eingebaut.

Grüße

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ACK polling ist hier auch besser als delay_ms ^^
>ack polling bis wieder frei ist dann weiterschreiben

Stimmt nicht in jedem Fall! Statt zu warten und solange nichts tun, 
könnten andere Tasks was sinvolles erledigen...

Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, im Moment komme ich ja nicht über das Schreiben der ersten Page 
hinaus... Wenn ich die Adresse dann neu Setze (nächste Page) und dann 
meiner Write funktion aufrufe, fängt diese an wieder die gleichen Daten 
wie auf der ersten Page zu schreiben...

Grüße

Bean

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"The 24XX128 does not generate any
Acknowledge bits if an internal
programming cycle is in progress."


genau das nutzt man da
man schreibt den eeprom so lange an bis dieser ein ACK liefert
und das war bei meinen eeprom bisher immer unter 5ms !!
je nach tagesform ^^


da is glaueb noch fehler drin ....

while( length )
 {
   page_cnt = PAGE_SIZE - (adress%PAGE_SIZE);
   startcondition
   eepromadresse + schreibbefehl
   datenadresse
   while( page_cnt )
    {
      daten senden
      length--;
      if(length == 0)
      break;
    }
    //  neue adresse = anfang der nächsten seite  // alte seite +1
    adress = ((adress/PAGE_SIZE)+1) * PAGE_SIZE;
    page_cnt = length;
    Stopkonition senden
    ack_polling  oder delay_ms(5)
 }

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du must ziwschen den pages eine stopkondition senden und warten
man kann nicht gleich weiterschreiben

also adresse ausrechnen , stop senden , warten
und dann weiterschreiben

das
      if(length == 0)
      break;

is für den fall das nicht über eine seite geschrieben wird ^^

Autor: Mr Bean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das Ganze jetzt nochmal umgeschrieben. Funktioniert aber leider 
immer noch nicht wie gewollt. So langsam wird die ganze Funktion auf 
recht groß finde ich...
int EEPROM_BUF_Write(unsigned int address, unsigned char buf[], unsigned int count)
{
  unsigned char retval;
  unsigned char ret;
  unsigned char sendbuf[PAGESIZE+2];
  unsigned char i, index;
  unsigned char bytenum = 0;
  
  bytenum = PAGESIZE - (address % PAGESIZE);
  
  if(count > PAGESIZE || count > bytenum)
  {
    LED = !LED;
    
    sendbuf[1] = address & 0xFF;
    sendbuf[0] = (address >> 8) & 0xFF;
    
    for(i = 0; i <= bytenum; i++)
    {
      sendbuf[i+2] = buf[i];
      address++;
      count--;
    }
    SMB_Write(EEPROM_ADDR, sendbuf, bytenum + 2);
    T2_Waitms(5);
    index = i;

    while((count / PAGESIZE) == 0)
    {
      
      sendbuf[1] = address & 0xFF;
      sendbuf[0] = (address >> 8) & 0xFF;
      
      for(i = 0; i <= PAGESIZE; i++)
      {
        sendbuf[i+2] = buf[index];
        index++;
        count--;
        address++;
      }
      SMB_Write(EEPROM_ADDR, sendbuf, PAGESIZE+2);
      T2_Waitms(5);
    }

    if(count > 0)
    {
      sendbuf[1] = address & 0xFF;
      sendbuf[0] = (address >> 8) & 0xFF;
      LED = !LED;
      for(i = 0; i <= count; i++)
      {
        sendbuf[i+2] = buf[index];
        index++;
        address++;
      }
      SMB_Write(EEPROM_ADDR, sendbuf, count+2);  
    }
  }
  
  else
  {
    sendbuf[1] = address & 0xFF;
    sendbuf[0] = (address >> 8) & 0xFF;
    
    for(i = 0; i <= count; i++)
    {
      sendbuf[i+2] = buf[i];
      address++;
    }

    ret = SMB_Write(EEPROM_ADDR, sendbuf, count+2);
    
    if(ret)
    {
      retval = EEPROMWRITEFAIL;
    }
    retval = EEPROMWRITESUCCESS;
  }
  return retval; 
}
Wenn ich mehr als eine Page schreiben möchte, wird nur die Adresse 
übertragen.... :-(

Grüße

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
frag ist warum buf ?

mach ein *char draus und fertig
damit kannst du auch array schreiben .. is ja kein ding

ein unsigned char buf[] als übergabe is schon kompliziert wenn man mal 
kein [] hat sondern ein struct ins eeprom schieben will
besser wäre hier vlt ein  void *data



und das da oben vin mir ..
while( length )
 {
   page_cnt = PAGE_SIZE - (adress%PAGE_SIZE);
   startcondition
   eepromadresse + schreibbefehl
   datenadresse
   while( page_cnt )
    {
      daten senden
      length--;
      if(length == 0)
      break;
    }
    //  neue adresse = anfang der nächsten seite  // alte seite +1
    adress = ((adress/PAGE_SIZE)+1) * PAGE_SIZE;
    page_cnt = length;
    Stopkondition senden
    ack_polling  oder delay_ms(5)
 }

ist so ziemlich das einzisgte in meiner funktion ...

ich weiß nich was deine SMB_Write(..) macht ..
sie darf aber in keinem fall ein STOP senden

page write :

start
eepromadresse
datenadresse
daten
daten
daten
.
.
..
daten
stop



bei überschreiten einer page :

start
eepromadresse
datenadresse
daten
daten
daten
.
pageende erreicht
STOP
5ms warten
start
eepromadresse
neue datenadresse
daten
daten
daten
.
..
daten
stop

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.