24LC128 EEPROM auslesen

Gast #1462721
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
Gast #1462869
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
Gast #1462895
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!
#1462932
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
Gast #1463508
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
Gast #1463534
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
Gast #1463537
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
Gast #1463543
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...
Gast #1463566
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
Gast #1463608
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)
 }
Gast #1463613
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 ^^
Gast #1463708
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
Gast #1463748
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren