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


von Michl (Gast)


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.

von holger (Gast)


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.

von Michl (Gast)


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

von holger (Gast)


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.

von (prx) A. K. (prx)


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?

von Michl (Gast)


Lesenswert?

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

von Michl (Gast)


Angehängte Dateien:

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.

von Peter D. (peda)


Lesenswert?

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


Peter

von Michl (Gast)


Lesenswert?

1
int Test_EEPROM (void)
2
{
3
  unsigned char eeprom_data;
4
  unsigned int address;
5
  int error_count = 0;
6
  
7
  // Block 0 beschreiben
8
  for (address = 0, eeprom_data = 0x00; address <= 0xff; address++, eeprom_data++)
9
  {
10
    EEPROM_Write (EEPROM_1, Block_0, address&0xFF, 1, (u8*)&eeprom_data);
11
  }
12
  
13
  // Block 1 beschreiben
14
  for (address = 0, eeprom_data = 0x00; address <= 0xff; address++, eeprom_data++)
15
  {
16
    EEPROM_Write (EEPROM_1, Block_1, address&0xFF, 1, (u8*)&eeprom_data);
17
  }
18
19
  eeprom_data = 0;    
20
  // Block 0 lesen
21
  for (address = 0; address <= 0xff; address++)
22
  {
23
    eeprom_data = (unsigned char)EEPROM_Read (EEPROM_1, Block_0, address&0xFF, 1);
24
    if (eeprom_data != address)
25
    {
26
      error_count++;
27
    }
28
  }
29
  
30
  eeprom_data = 0;
31
  // Block 1 lesen
32
  for (address = 0; address <= 0xff; address++)
33
  {
34
    eeprom_data = (unsigned char)EEPROM_Read (EEPROM_1, Block_1, address&0xFF, 1);
35
//    eeprom_data = *pTWI_RCV_DATA8;
36
    
37
    if (eeprom_data != address)
38
    {
39
      error_count++;
40
    }
41
  }
42
  
43
  return error_count;
44
}
45
46
void EEPROM_Write (u8 eeprom, u8 block, u8 address, u8 datasize, u8 *data)
47
{
48
  do
49
  {
50
    if (*pTWI_MASTER_STAT & ANAK)
51
      *pTWI_MASTER_STAT |= ANAK;    // Adress-NAK-Bit zurücksetzen
52
    xmt   = 0;
53
    mcomp = 0;
54
  
55
    TWI_TxPtr = data;          // Pointer auf Daten
56
    *pTWI_XMT_DATA8 = address;      // Adresse in FIFO laden
57
    EEPROM_Select (eeprom, block);    // EEPROM auswählen, hierzu müssen Daten im FIFO sein, ansonsten Fehler (siehe HW_Ref)
58
    TWI_Write (datasize + 1);      // Tx beginnen
59
    
60
    while((*pTWI_MASTER_STAT & BUSBUSY) || (*pTWI_MASTER_STAT & MPROG));  // Auf Tx_Ende warten
61
    
62
    TWI_Next_Cycle = 0;    
63
    while(!TWI_Next_Cycle);        // 10ms warten -> EEPROM Write Time!
64
  
65
  }while(*pTWI_MASTER_STAT & ANAK);    // Bei Adress-NAK nochmals versuchen
66
  
67
}
68
69
70
71
int EEPROM_Read (u8 eeprom, u8 block, u8 address, u8 datasize)
72
{
73
  unsigned char Rx_Data = 0;
74
  
75
  Restart_bytes_to_read = datasize;
76
  Restart_Flag = 1;
77
78
  *pTWI_XMT_DATA8 = address;      // Adresse in FIFO laden
79
  EEPROM_Select (eeprom, block);    // EEPROM auswählen, hierzu müssen Daten im FIFO sein, ansonsten Fehler (siehe HW_Ref)
80
  TWI_Write (1);            // Tx beginnen  
81
  TWI_RxPtr = (u8*)&Rx_Data;
82
  
83
  TWI_Next_Cycle = 0;
84
  while(!TWI_Next_Cycle);
85
  while((*pTWI_MASTER_STAT & BUSBUSY) || (*pTWI_MASTER_STAT & MPROG));  // Auf Tx_Ende warten
86
87
  return Rx_Data;
88
}
89
90
// Und hier die ISR
91
// TWI
92
  if (*pSIC_ISR & IRQ_TWI)
93
  {
94
95
    if (*pTWI_INT_STAT & MCOMP)          // Transfer Complete
96
    {
97
      *pTWI_INT_STAT |= MCOMP;        // Clear Interrupt 
98
      
99
      if (*pTWI_MASTER_CTL & RSTART)
100
      {
101
        *pTWI_MASTER_CTL &= ~RSTART;
102
        Restart_Flag = 0;
103
        *pTWI_MASTER_CTL |= ((Restart_bytes_to_read) << 6);
104
      }
105
      
106
      mcomp++;
107
    }
108
    
109
    if (*pTWI_INT_STAT & XMTSERV)        // Transfer IRQ
110
    {
111
      if ((*pTWI_MASTER_CTL & DCNT) > 40)    // Load next data if DCNT is > 1
112
        *pTWI_XMT_DATA8 = *TWI_TxPtr++;  // Otherwise data transfer will be completed in next cycle
113
        
114
        
115
      if (((*pTWI_MASTER_CTL & DCNT) == 0) && (Restart_Flag == 1))
116
      {
117
        *pTWI_MASTER_CTL |= RSTART;
118
        *pTWI_MASTER_CTL |= MDIR;
119
      }
120
      *pTWI_INT_STAT |= XMTSERV;        // Clear Interrupt 
121
      xmt++;
122
      
123
    }
124
    
125
    if (*pTWI_INT_STAT & MERR)
126
    {
127
      *pTWI_INT_STAT |= MERR;    // Clear Interrupt
128
      merr = *pTWI_MASTER_STAT;  // Save Master Status
129
    }
130
    
131
    
132
    if (*pTWI_INT_STAT & RCVSERV)      // Read IRQ
133
    {
134
      *pTWI_INT_STAT |= RCVSERV;      // Clear Interrupt
135
      *TWI_RxPtr++ = *pTWI_RCV_DATA8;    // Save received Byte
136
      rcv++;
137
    }
138
    
139
    
140
141
    ssync();
142
  }

Das ganze läuft auf einem BlackFin.

von Peter D. (peda)


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

von Michl (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


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.

von Thomas (Gast)


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

von Peter D. (peda)


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

von Michl (Gast)


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.

von Michl (Gast)


Lesenswert?

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

von Michl (Gast)


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

von Michl (Gast)


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

von Michl (Gast)


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.

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.