mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ST24c04 - Nur erster Block lässt sich beschreiben


Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute, ich habe ein EEPROM mit 4Kbit von ST im Einsatz. Die genaue 
Bezeichnung lautet ST24c04, siehe Datenblatt im Anhang.

Beschaltet ist es folgendermaßen:
SDA, SCLK entsprechd mit Pullups an µC.
Vcc und Mode an 3,3V.
Vss, E1, E2 und PRE auf Masse.

Wenn ich als BlockSelect-Bit 0 wähle, dann die 256Byte beschreibe und 
anschließend auslese, stimmen die Werte.
Wähle ich die oberen 256Byte, dann stimmen die Werte nicht mehr. Laut 
Oszi werden die richtigen Daten übertragen beim Beschreiben, auch die 
ACKs kommen.
Zwischen den jeweiligen Schreibzyklen wird 10ms gewartet gemäß tw im 
Datenblatt.

Das komische ist eben, dass das nur bei den ersten 256Byte auftritt.

Hat jemand eine Idee woran es liegen könnte? Ich habe auch schon mehrere 
EEPROMs der gleichen Version ausprobiert.

Vielen Dank.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hat jemand eine Idee woran es liegen könnte? Ich habe auch schon mehrere
>EEPROMs der gleichen Version ausprobiert.

Das liegt an deinem Programm.

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo, das wär natürlich noch ne Möglichkeit. Komisch ist eben nur, dass es 
beim ersten Block dann reibungslos funktioniert.
Was ich noch nachtragen muss:

Wenn ich den zweiten Block mit 0x00 beschreibe, stimmts. Ich lese 
anschließend wirklich auf 0x00 aus. Mit dem Oszi überprüft.

Hat jemand schonmal was ähnliches gehabt? Gerade beim ST.?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Jo, das wär natürlich noch ne Möglichkeit.

Möglichkeit? Du hast ein Softwareproblem;)

>Hat jemand schonmal was ähnliches gehabt? Gerade beim ST.?

Nö, kann immer locker vom Anfang bis zum Ende programmiert
werden. Hardwarefehler haben die nicht.

Der Fehler liegt wie immer in Zeile 42 oder sitzt vor dem Bildschirm.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du das erste Byte beider Hälften mit einem unterschiedlichen Inhalt 
beschreibst, wobei das weder lauter Nullen noch lauter Einsen sein 
sollten, was steht dann hinterher drin?

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ALso, habe jeweils das erste Byte jedes Blcoks mit 0x57 beschrieben.
Erster Block stimmt, ich lese 0x57.
Beim zweiten Block lese ich 0x47.

Autor: Michl (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang mal noch die Oszibilder beim jeweiligen Vorgang. Beim Lesen 
wird in der Mitte ungefähr eine wiederholter Start eingeleitet.
Alles wird richtig "ge-ackt" und auch am Ende des Lesens kommt ein NAK.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön.
Jetzt bräuchte man bloß noch einen Timing nach C-Code Umsetzer.


Peter

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int Test_EEPROM (void)
{
  unsigned char eeprom_data;
  unsigned int address;
  int error_count = 0;
  
  // Block 0 beschreiben
  for (address = 0, eeprom_data = 0x00; address <= 0xff; address++, eeprom_data++)
  {
    EEPROM_Write (EEPROM_1, Block_0, address&0xFF, 1, (u8*)&eeprom_data);
  }
  
  // Block 1 beschreiben
  for (address = 0, eeprom_data = 0x00; address <= 0xff; address++, eeprom_data++)
  {
    EEPROM_Write (EEPROM_1, Block_1, address&0xFF, 1, (u8*)&eeprom_data);
  }

  eeprom_data = 0;    
  // Block 0 lesen
  for (address = 0; address <= 0xff; address++)
  {
    eeprom_data = (unsigned char)EEPROM_Read (EEPROM_1, Block_0, address&0xFF, 1);
    if (eeprom_data != address)
    {
      error_count++;
    }
  }
  
  eeprom_data = 0;
  // Block 1 lesen
  for (address = 0; address <= 0xff; address++)
  {
    eeprom_data = (unsigned char)EEPROM_Read (EEPROM_1, Block_1, address&0xFF, 1);
//    eeprom_data = *pTWI_RCV_DATA8;
    
    if (eeprom_data != address)
    {
      error_count++;
    }
  }
  
  return error_count;
}

void EEPROM_Write (u8 eeprom, u8 block, u8 address, u8 datasize, u8 *data)
{
  do
  {
    if (*pTWI_MASTER_STAT & ANAK)
      *pTWI_MASTER_STAT |= ANAK;    // Adress-NAK-Bit zurücksetzen
    xmt   = 0;
    mcomp = 0;
  
    TWI_TxPtr = data;          // Pointer auf Daten
    *pTWI_XMT_DATA8 = address;      // Adresse in FIFO laden
    EEPROM_Select (eeprom, block);    // EEPROM auswählen, hierzu müssen Daten im FIFO sein, ansonsten Fehler (siehe HW_Ref)
    TWI_Write (datasize + 1);      // Tx beginnen
    
    while((*pTWI_MASTER_STAT & BUSBUSY) || (*pTWI_MASTER_STAT & MPROG));  // Auf Tx_Ende warten
    
    TWI_Next_Cycle = 0;    
    while(!TWI_Next_Cycle);        // 10ms warten -> EEPROM Write Time!
  
  }while(*pTWI_MASTER_STAT & ANAK);    // Bei Adress-NAK nochmals versuchen
  
}



int EEPROM_Read (u8 eeprom, u8 block, u8 address, u8 datasize)
{
  unsigned char Rx_Data = 0;
  
  Restart_bytes_to_read = datasize;
  Restart_Flag = 1;

  *pTWI_XMT_DATA8 = address;      // Adresse in FIFO laden
  EEPROM_Select (eeprom, block);    // EEPROM auswählen, hierzu müssen Daten im FIFO sein, ansonsten Fehler (siehe HW_Ref)
  TWI_Write (1);            // Tx beginnen  
  TWI_RxPtr = (u8*)&Rx_Data;
  
  TWI_Next_Cycle = 0;
  while(!TWI_Next_Cycle);
  while((*pTWI_MASTER_STAT & BUSBUSY) || (*pTWI_MASTER_STAT & MPROG));  // Auf Tx_Ende warten

  return Rx_Data;
}

// Und hier die ISR
// TWI
  if (*pSIC_ISR & IRQ_TWI)
  {

    if (*pTWI_INT_STAT & MCOMP)          // Transfer Complete
    {
      *pTWI_INT_STAT |= MCOMP;        // Clear Interrupt 
      
      if (*pTWI_MASTER_CTL & RSTART)
      {
        *pTWI_MASTER_CTL &= ~RSTART;
        Restart_Flag = 0;
        *pTWI_MASTER_CTL |= ((Restart_bytes_to_read) << 6);
      }
      
      mcomp++;
    }
    
    if (*pTWI_INT_STAT & XMTSERV)        // Transfer IRQ
    {
      if ((*pTWI_MASTER_CTL & DCNT) > 40)    // Load next data if DCNT is > 1
        *pTWI_XMT_DATA8 = *TWI_TxPtr++;  // Otherwise data transfer will be completed in next cycle
        
        
      if (((*pTWI_MASTER_CTL & DCNT) == 0) && (Restart_Flag == 1))
      {
        *pTWI_MASTER_CTL |= RSTART;
        *pTWI_MASTER_CTL |= MDIR;
      }
      *pTWI_INT_STAT |= XMTSERV;        // Clear Interrupt 
      xmt++;
      
    }
    
    if (*pTWI_INT_STAT & MERR)
    {
      *pTWI_INT_STAT |= MERR;    // Clear Interrupt
      merr = *pTWI_MASTER_STAT;  // Save Master Status
    }
    
    
    if (*pTWI_INT_STAT & RCVSERV)      // Read IRQ
    {
      *pTWI_INT_STAT |= RCVSERV;      // Clear Interrupt
      *TWI_RxPtr++ = *pTWI_RCV_DATA8;    // Save received Byte
      rcv++;
    }
    
    

    ssync();
  }

Das ganze läuft auf einem BlackFin.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wundert mich nicht, daß es nicht funktioniert.
Du hast ne Menge zusätzlicher Fehlermöglichkeiten (Interrupt, HW-I2C).

Machs erstmal zu Fuß (SW-I2C, keine Interrupts).

Außerdem fehlen Funktionen, z.B. EEPROM_Select.
Quelltexte als Anhang mit allem zum Compilieren nötigem!


Peter

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, aber kann ich davon ausgehen, dass das Schreiben funktioniert, oder.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michl schrieb:

> Ok, aber kann ich davon ausgehen, dass das Schreiben funktioniert, oder.

Das könntest du, wenn sich mit einem anderen bekannt funktionsfähigen 
I2C-Interface der Inhalt verifizieren liesse.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ok, aber kann ich davon ausgehen, dass das Schreiben funktioniert

Ich glaube das ehrlich gesagz nicht. Vermutlich schreibst du immer
in den Block 0.

Was macht denn dein EEprom_Select genau?
Du weist wie bei den EEproms >256 Bytes die Blöcke addressiert werden?

Thomas

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michl schrieb:
> Ok, aber kann ich davon ausgehen, dass das Schreiben funktioniert, oder.

Weiß ich nicht, ich kenne das TWI und den Interruptcontroller Deines MC 
nicht.

Du weißt aber schon, daß man immer nur ein Byte oder eine Page schreiben 
kann?


Peter

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein EEPROM_Select setzt die Adresse des EEPROMS zusammen. Also 0b1010 
und dann eben 0b00hintendran für die hardwired Adresse sowie eine 0 für 
Block 0 bzw. eine 1 für Block 1 hinten dran.

Ergo: Block 0 = 0b1010000
      Block 1 = 0b1010001

Das kommt ja auch raus laut Oszi.

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei diesem EEPROM kann man auch noch MultiByte schreiben -> siehe 
Datenblatt, MODE-Pin. Dann sinds 4 Byte.

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich von Adresse 0x00 bis 0xFF den jweiligen Adresswert reinschreib, 
also 0x00 auf 0x00, 0x5a auf 0x5a usw, dann ergibt sich folgendes 
"Bild":

Adresse   Daten
  x0       00
  x1       x1
  x2       x2
  x3       x3
  x4       x4
  x5       x5
  x6       x6
  x7       x7
  x8       x8
  x9       x9
  xa       xa
  xb       xb
  xc       xc
  x1       x1  <-- falsch
  x2       x2  <-- falsch
  xf       xf

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe das EEPROM mal mit einem externen Lesegerät ausgelesen. Werte 
werden korrekt geschrieben.
Also liegts am Lesen, wobei die Adressen stimmen laut Oszi. Ominös 
iwie...

Autor: Michl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das Problem immer noch.
Kann jmd. die Leseübertragung anhand der Oszi-Bilder und des Datenblatts 
verifizieren? Meiner Meinung nach stimmt was ich LESE und ÜBERTRAGEN 
wird.

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.