Forum: Mikrocontroller und Digitale Elektronik SPI EEProm Hilfe gesucht


von TobyTetzi (Gast)


Lesenswert?

Hallo,

ich nutze einen SPI EEProm, M95256 von ST, an einem ATmega8.

Nun habe ich folgendes Problem:

Ich beschreibe mit folgender C Routine den EEProm mit Daten, die er UART 
rein kommen:

// Definition der Leds
//#define ANZAHL_LEDS 8
//#define ANZAHL_LEDS 16
//#define ANZAHL_LEDS 24
//#define ANZAHL_LEDS 32
//#define ANZAHL_LEDS 40
#define ANZAHL_LEDS 48
//#define ANZAHL_LEDS 56
//#define ANZAHL_LEDS 64

// Definition der Bytes pro Spalte
#define ANZAHL_BYTES  ( ANZAHL_LEDS / 8 )

void Write_SPI_EEProm (void){

BYTE HighAdress = 0;
BYTE LowAdress = 0;
BYTE Daten[ANZAHL_BYTES];
BYTE i = 0;

while(RxBufferStatus()==0);
myReceivedByte = RxBufferLesen();
if(myReceivedByte==':'){

  while(RxBufferStatus()==0);
    HighAdress = RxBufferLesen();
  while(RxBufferStatus()==0);
    LowAdress = RxBufferLesen();

  for( i = 0; i < ANZAHL_BYTES; ++i ) {
    while(RxBufferStatus()==0);
    Daten[i] = RxBufferLesen();
  }


  //status = Read_EEProm_Status();
  //if ( status == 0b00000000 ){
  //while(Read_EEProm_Status()!=0);
  //while(Read_EEProm_Status()!=0);

  cbi(PORTB,0);
  spiTransferByte(0b00000110);//write enable WREN
  sbi(PORTB,0);
  cbi(PORTB,0);
  spiTransferByte(0b00000010);//write command
  spiTransferByte(HighAdress);//high adresse
  spiTransferByte(LowAdress);  //low adresse

  for( i = 0; i < ANZAHL_BYTES; ++i )
    spiTransferByte( Daten[i] );

  sbi(PORTB,0);

  nop;nop;nop;nop;nop;

  // Write disable
  cbi(PORTB,0);
  spiTransferByte(0b00000100);//write disable WRDI
  sbi(PORTB,0);

  nop;nop;nop;nop;nop;

while(RxBufferStatus()==0);
myReceivedByte = RxBufferLesen();
if(myReceivedByte==';'){

  //Bestätigung schicken
  TxDatenSenden('O');

    }
  }
}

Mit folgender Routine lese ich den EEProm aus, und sende die Daten per 
UART an den PC:

void Read_SPI_EEProm (void){

BYTE HighAdress = 0;
BYTE LowAdress = 0;
BYTE Daten[ANZAHL_BYTES];
BYTE i = 0;

while(RxBufferStatus()==0);
myReceivedByte = RxBufferLesen();
if(myReceivedByte==':'){

  while(RxBufferStatus()==0);
  HighAdress = RxBufferLesen();
  while(RxBufferStatus()==0);
  LowAdress = RxBufferLesen();

  //status = Read_EEProm_Status();
  //if ( status == 0b00000000 ){
  //while(Read_EEProm_Status()!=0);

  cbi(PORTB,0);
  spiTransferByte(0b00000011);  //read command
  spiTransferByte(HighAdress);  //high adresse
  spiTransferByte(LowAdress);  //low adresse

  for( i = 0; i < ANZAHL_BYTES; ++i ){
  Daten[i] = spiTransferByte(0b00000000);
    }

  sbi(PORTB,0);

while(RxBufferStatus()==0);
myReceivedByte = RxBufferLesen();
if(myReceivedByte==';'){

  //Daten mit "D" ankündigen, PC wartet, bis "D" kommt
  TxDatenSenden('D');

  for( i = 0; i < ANZAHL_BYTES; ++i )
   TxDatenSenden( Daten[i] );

   }
  }
}

Nun klappt Alles so weit ganz gut.
Das PC Programm erstellt mir eine Datei, mit den Daten : Highadresse, 
Lowadresse, EEPromDaten.
Allerdings bekomme ich Fehler, wenn ich 3,5,6,7 Bytes pro Adresse 
schreibe.
(Das ich umgekehrt lese, wie schreibe, abe ich schon bemerkt!)

Bei 2 Bytes pro Adresse sieht die Datei des PC Programms beispielweise 
so aus (EEPromdaten = 0xFF,0x00):

Schreiben:
W: 0 0 (ÿ );
W: 0 2 (ÿ );
W: 0 4 (ÿ );
W: 0 6 (ÿ );
W: 0 8 (ÿ );
W: 0 10 (ÿ );
W: 0 12 (ÿ );
W: 0 14 (ÿ );
W: 0 16 (ÿ );
W: 0 18 (ÿ );
W: 0 20 (ÿ );
W: 0 22 (ÿ );
W: 0 24 (ÿ );
...
...

Lesen:
R: 0 0 ( ÿ);
R: 0 2 ( ÿ);
R: 0 4 ( ÿ);
R: 0 6 ( ÿ);
R: 0 8 ( ÿ);
R: 0 10 ( ÿ);
R: 0 12 ( ÿ);
R: 0 14 ( ÿ);
R: 0 16 ( ÿ);
R: 0 18 ( ÿ);
R: 0 20 ( ÿ);
R: 0 22 ( ÿ);
R: 0 24 ( ÿ);
...
...

Nun aber bei 6 Bytes bekomme ich folgendes:
(EEPromdaten = 0xFF,0x00,0x00,0x00,0x00,0x00)

Schreiben:
W: 0 0 (ÿ     );
W: 0 6 (ÿ     );
W: 0 12 (ÿ     );
W: 0 18 (ÿ     );
W: 0 24 (ÿ     );
W: 0 30 (ÿ     );
W: 0 36 (ÿ     );
W: 0 42 (ÿ     );
W: 0 48 (ÿ     );
W: 0 54 (ÿ     );
W: 0 60 (ÿ     );
W: 0 66 (ÿ     );
W: 0 72 (ÿ     );
W: 0 78 (ÿ     );
W: 0 84 (ÿ     );
W: 0 90 (ÿ     );
W: 0 96 (ÿ     );
W: 0 102 (ÿ     );
W: 0 108 (ÿ     );
W: 0 114 (ÿ     );
W: 0 120 (ÿ     );
W: 0 126 (ÿ     );
W: 0 132 (ÿ     );
W: 0 138 (ÿ     );
W: 0 144 (ÿ     );
W: 0 150 (ÿ     );
W: 0 156 (ÿ     );
W: 0 162 (ÿ     );
W: 0 168 (ÿ     );
W: 0 174 (ÿ     );
W: 0 180 (ÿ     );
W: 0 186 (ÿ     );
W: 0 192 (ÿ     );
W: 0 198 (ÿ     );
W: 0 204 (ÿ     );
W: 0 210 (ÿ     );
W: 0 216 (ÿ     );
W: 0 222 (ÿ     );
W: 0 228 (ÿ     );
W: 0 234 (ÿ     );
W: 0 240 (ÿ     );
W: 0 246 (ÿ     );
W: 0 252 (ÿ     );
W: 1 2 (ÿ     );
...
...

Lesen:
R: 0 0 (      );   ??????Wo sind die Daten hin?????
R: 0 6 (     ÿ);
R: 0 12 (     ÿ);
R: 0 18 (     ÿ);
R: 0 24 (     ÿ);
R: 0 30 (     ÿ);
R: 0 36 (     ÿ);
R: 0 42 (     ÿ);
R: 0 48 (     ÿ);
R: 0 54 (     ÿ);
R: 0 60 (     ÿ);
R: 0 66 (      );   ??????Wo sind die Daten hin?????
R: 0 72 (     ÿ);
R: 0 78 (     ÿ);
R: 0 84 (     ÿ);
R: 0 90 (     ÿ);
R: 0 96 (     ÿ);
R: 0 102 (     ÿ);
R: 0 108 (     ÿ);
R: 0 114 (     ÿ);
R: 0 120 (     ÿ);
R: 0 126 (   ð ÿ);   ??????Was sind das für Daten?????
R: 0 132 (     ÿ);
R: 0 138 (     ÿ);
R: 0 144 (     ÿ);
R: 0 150 (     ÿ);
R: 0 156 (     ÿ);
R: 0 162 (     ÿ);
R: 0 168 (     ÿ);
R: 0 174 (     ÿ);
R: 0 180 (     ÿ);
R: 0 186 (     ÿ);
R: 0 192 (      );   ??????Wo sind die Daten hin?????
R: 0 198 (     ÿ);
R: 0 204 (     ÿ);
R: 0 210 (     ÿ);
R: 0 216 (     ÿ);
R: 0 222 (     ÿ);
R: 0 228 (     ÿ);
R: 0 234 (     ÿ);
R: 0 240 (     ÿ);
R: 0 246 (     ÿ);
R: 0 252 (     ÿ);
R: 1 2 (      );   ??????Wo sind die Daten hin?????
...
...

Woran kann das liegen?
Hat es etwa etwas mit dem PageWrite des EEProms zu tun?
Liegt es nun am Schreiben, oder am Lesen?

Für etwas Hilfe wäre ich sehr dankbar!

Gruß Toby

von TobyTetzi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

anliegend ist nochmal das Datenblatt zum besagten EEProm.

Gruß Toby

von TobyTetzi (Gast)


Lesenswert?

Hallo nochmal,

weiß denn wirklichkeiner einen Rat?

Gruß Toby

von Florian (Gast)


Lesenswert?

Du musst immer, wenn Du eine Page-Grenze erreichts, neu ansetzen. So 
verstehe ich zumindest das Datenblatt:

If the number of data bytes sent to
the device exceeds the page boundary, the internal
address counter rolls over to the beginning of
the page, and the previous data there are overwritten
with the incoming data. (The page size of
these devices is 64 bytes).

Bist Du außerdem sicher, dass Du die Timings korrekt beachtest?

von TobyTetzi (Gast)


Lesenswert?

Hallo Florian,

danke für deine Antwort.
ich habe mir so etwas mit der Page schon gedach, allerdings das 
Datenblatt nicht ganz verstanden.

Also, teile ich die 64 Byte pro Page durch meine zu schreibendnen Bytes, 
muß es immer eine Ganzzahl ergeben:

64/2 = 32       geht, wenn ich immer 2 Bytes schreibe.
64/3 = 21,33333 geht nicht, wenn 3 Bytes schreibe.
64/4 = 16       geht, wenn ich immer 4 Bytes schreibe.
64/5 = 12,8     geht nicht, wenn 5 Bytes schreibe.
64/6 = 10,6666  geht nicht, wenn 6 Bytes schreibe.
64/7 = 9,142    geht nicht, wenn 7 Bytes schreibe.
64/8 = 8        geht, wenn ich immer 8 Bytes schreibe.

Das mit dem Timing sollte hin hauen, da es ja bei 2,4 und 8 Bytes geht.

Wo gäbe es denn verbesserungen an meinem Code?

Gruß Toby



von Magnus Müller (Gast)


Lesenswert?

Du kannst immer nur innerhalb eines 64Bit-Blocks schreiben.

Zu schreiben sind jeweils 1 bis 64 Bytes.

Man kann auch mehr als 64 Bytes auf einmal schicken, es werden aber nur 
die letzten 64 Bytes geschrieben.

Initiiert man einen Schreibvorgang an Adresse 63(dez.) und gibt dem 
EEPROM zwei zu schreibende Bytes (z.B. 0xAA und 0x55) mit, so wird 
0xAA an Adresse 63 und 0x55 an Adresse 0(!) abgelegt.

von TobyTetzi (Gast)


Lesenswert?

Hallo Magnus,

daher kommt es auch, das ich hier:

Lesen:
R: 0 0 (      );   ??????Wo sind die Daten hin?????
R: 0 6 (     ÿ);
R: 0 12 (     ÿ);

Das ich in Adresse 0 nichts mehr habe,
da ich ja hier:

W: 0 54 (ÿ     );
W: 0 60 (ÿ     );
W: 0 66 (ÿ     );

bei Adresse 0 60 (dez) 6 bytes schreiben will.
Beim 3. byte bin ich ja schon an Adresse 0 63 (dez),
also wird das 4. byte nicht in Adresse 0 64,
sondern am Anfang dieser Page, Adresse 0 0 gespeichert.
Ich müsste also nach insgesammt 64 geschriebenen Bytes (ab Adresse 0 0) 
wieder einen Schreibvorgang starten, der bei Page 2, also Adresse 0 64 
(dez) beginnt.

Oder nochmal anders gesagt, ich darf, wenn ich mehrere bytes ab einer 
bestimmten Adresse schreiben will, nie die Pagegrenze überschreiten.

Ok, dann muß ich mein VB Programm ändern.

Danke und Gruß Toby

von Magnus Müller (Gast)


Lesenswert?

Bitteschön ;) und weiterhin gutes Gelingen!

Gruß,
Magnetus

[Edit]

P.S.:  Der entscheidende Hinweis kam von Florian (Gast). Ich hab
       nichts anderes getan, als ein kleines Beispiel zu nennen.

       --> Vielen Dank an Florian (Gast)

von TobyTetzi (Gast)


Lesenswert?

Oh, ein Fehler, sorry.
Es muß nicht das 3. byte bei Adresse 63 heißen, es ist ja schon das 4. 
byte.

W: 0 60 (123456);

Ich müßte also, um das 5. und 6. Byte zu schreiben, einen neuen 
Schreibvorgang starten.



Noch eine Frage, ist es beim lesen auch so????

Gruß Toby

von Magnus Müller (Gast)


Lesenswert?

TobyTetzi wrote:
> Oh, ein Fehler, sorry.
> Es muß nicht das 3. byte bei Adresse 63 heißen, es ist ja schon das 4.
> byte.
>
> W: 0 60 (123456);
>
> Ich müßte also, um das 5. und 6. Byte zu schreiben, einen neuen
> Schreibvorgang starten.
>
>
>
> Noch eine Frage, ist es beim lesen auch so????
>
> Gruß Toby

Siehe Datenblatt Seite 17.

Beim Lesen gibt es die Page-Beschränkung nicht. Ein fortlaufender 
Lesevorgang wird nur durch die Speichergröße (im konkreten Fall 32KB) 
begrenzt. Erreichst du beim fortlaufenden Lesen das Speicherende 
(Adresse 0x7FFF), so erhältst du mit den nächsten Bytes die Inhalte der 
Adressen 0x0000, 0x0001 usw.

Gruß,
Magnetus

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.