Forum: Mikrocontroller und Digitale Elektronik 24LC128 EEPROM auslesen


von Mr Bean (Gast)


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

von Falk B. (falk)


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

von Mr Bean (Gast)


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

von Falk B. (falk)


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

von Ralf (Gast)


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

von Mr Bean (Gast)


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!

von Falk B. (falk)


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

von Mr Bean (Gast)


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:
1
int EEPROM_BUF_Write(unsigned int address, unsigned char buf[], unsigned int count)
2
{
3
  unsigned char retval;
4
  unsigned char I2Cstat;
5
  unsigned char sendbuf[PAGESIZE];
6
  unsigned char i=0;
7
  unsigned int pos = 0;
8
  unsigned char bytenum = 0;
9
10
  sendbuf[1] = address & 0xFF;
11
  sendbuf[0] = (address >> 8) & 0xFF;
12
  
13
  if(count > PAGESIZE)
14
  {
15
    pos = address % PAGESIZE;
16
    bytenum = PAGESIZE - pos;
17
    
18
    SMB_Write(EEPROM_ADDR, sendbuf, 2);
19
  
20
    while(i <= bytenum)
21
    {
22
      SMB_Write(EEPROM_ADDR, buf, bytenum);
23
      count--;
24
      address++;
25
      i++;
26
    }
27
    sendbuf[1] = address & 0xFF;
28
    sendbuf[0] = (address >> 8) & 0xFF;
29
    SMB_Write(EEPROM_ADDR, sendbuf, 2);
30
31
  }
32
  
33
  else
34
  {
35
    SMB_Write(EEPROM_ADDR, sendbuf, 2);
36
    I2Cstat = SMB_Write(EEPROM_ADDR, buf, count);
37
    if(I2Cstat)
38
    {
39
      retval = EEPROMWRITEFAIL;
40
    }
41
    retval = EEPROMWRITESUCCESS;
42
  }
43
  return retval; 
44
}

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

von Peter (Gast)


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...

von gast (Gast)


Lesenswert?

ACK polling ist hier auch besser als delay_ms ^^
ack polling bis wieder frei ist dann weiterschreiben

von gast (Gast)


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

von Mr Bean (Gast)


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

von Peter (Gast)


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...

von Mr Bean (Gast)


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

von gast (Gast)


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)
 }

von gast (Gast)


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 ^^

von Mr Bean (Gast)


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...
1
int EEPROM_BUF_Write(unsigned int address, unsigned char buf[], unsigned int count)
2
{
3
  unsigned char retval;
4
  unsigned char ret;
5
  unsigned char sendbuf[PAGESIZE+2];
6
  unsigned char i, index;
7
  unsigned char bytenum = 0;
8
  
9
  bytenum = PAGESIZE - (address % PAGESIZE);
10
  
11
  if(count > PAGESIZE || count > bytenum)
12
  {
13
    LED = !LED;
14
    
15
    sendbuf[1] = address & 0xFF;
16
    sendbuf[0] = (address >> 8) & 0xFF;
17
    
18
    for(i = 0; i <= bytenum; i++)
19
    {
20
      sendbuf[i+2] = buf[i];
21
      address++;
22
      count--;
23
    }
24
    SMB_Write(EEPROM_ADDR, sendbuf, bytenum + 2);
25
    T2_Waitms(5);
26
    index = i;
27
28
    while((count / PAGESIZE) == 0)
29
    {
30
      
31
      sendbuf[1] = address & 0xFF;
32
      sendbuf[0] = (address >> 8) & 0xFF;
33
      
34
      for(i = 0; i <= PAGESIZE; i++)
35
      {
36
        sendbuf[i+2] = buf[index];
37
        index++;
38
        count--;
39
        address++;
40
      }
41
      SMB_Write(EEPROM_ADDR, sendbuf, PAGESIZE+2);
42
      T2_Waitms(5);
43
    }
44
45
    if(count > 0)
46
    {
47
      sendbuf[1] = address & 0xFF;
48
      sendbuf[0] = (address >> 8) & 0xFF;
49
      LED = !LED;
50
      for(i = 0; i <= count; i++)
51
      {
52
        sendbuf[i+2] = buf[index];
53
        index++;
54
        address++;
55
      }
56
      SMB_Write(EEPROM_ADDR, sendbuf, count+2);  
57
    }
58
  }
59
  
60
  else
61
  {
62
    sendbuf[1] = address & 0xFF;
63
    sendbuf[0] = (address >> 8) & 0xFF;
64
    
65
    for(i = 0; i <= count; i++)
66
    {
67
      sendbuf[i+2] = buf[i];
68
      address++;
69
    }
70
71
    ret = SMB_Write(EEPROM_ADDR, sendbuf, count+2);
72
    
73
    if(ret)
74
    {
75
      retval = EEPROMWRITEFAIL;
76
    }
77
    retval = EEPROMWRITESUCCESS;
78
  }
79
  return retval; 
80
}
Wenn ich mehr als eine Page schreiben möchte, wird nur die Adresse 
übertragen.... :-(

Grüße

von gast (Gast)


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

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
Noch kein Account? Hier anmelden.