Forum: Mikrocontroller und Digitale Elektronik I2C-EEPROM im Arduino


von Alexander S. (knut740)


Lesenswert?

Hallo,
das Lesen (und vielleicht auch Schreiben) in einem per I2C mit einem 
Arduino verbundenen EEPROM funktioniert nicht.

Ich habe auf der Website des Lieferanten ein Beispielprogramm gefunden 
auf Basis der library <Wire.h>.
Aber bei der dort aufgelisteten Startinstruktion
   Wire.beginTransmission(deviceaddress);
wo ja eigentlich noch nichts weiter geschieht, bleibt das Programm schon 
hängen. In Wire.h ist die Instruktion ordnungsgemäß aufgelistet und in 
Wire.cpp sieht es unverdächtig aus, aber mangels tieferen Verständnis 
kann ich es nicht nachvollziehen.

Hat jemand eine Ahnung, ob es eine andere library für I2C-EEPROMS gibt 
oder muß man das Rad neu erfinden?


Gruß
knut

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?


von PittyJ (Gast)


Lesenswert?

Vielleicht solltest du das "mangels tieferen Verständnis" aufgeben, und 
verstehen wollen, was da passiert.

EEprom <-> Arduino: Sind die richtig verbunden? Mit Strom versorgt? Sind 
die Pins richtig eingestellt. Evtl mal Oszi anschliessen.
Die Wire-Bibliothek arbeitet eigentlich recht zuverlässig, habe schon 
mehrere Sensoren dort angeschlossen. Ohne deinen Source-Code kommt man 
hier nicht weiter.

Wenn bei
Wire.beginTransmission(deviceaddress);
nicht geschieht, warum läßt man es nicht weg? Anscheinend geschieht da 
doch was.

von Alexander S. (knut740)


Lesenswert?

PittyJ schrieb:

Endlich komme ich dazu, die angefangene Sache fortzusetzen.

> Vielleicht solltest du das "mangels tieferen Verständnis" aufgeben, und
> verstehen wollen, was da passiert.

Würde ich gern; ich komme, wenn ich die Instruktionen zurückverfolge, 
über Wire.h und Wire.cpp schließlich zu twi.h bzw. twi.c.

Da das Programm bei Wire.requestFrom (s.u.) hängen bleibt, führt der Weg 
durch die includierden Programme zu
 twi_readFrom  in TWI.c.
In diesem Unterprogramm kommt man nach einigen unzutreffenden 
Fehlerbedingungen schließlich zu
    while(TWI_READY != twi_state)
entweder antwortet der Chip nicht oder die Ports sind nicht richtig 
gesetzt (oder es bleibt später hängen).

Bevor ich jedoch die Schritte, Variablen und Portbezeichnungen mühselig 
nachvollziehe, hatte erst mal versucht, herauszufinden, an welcher 
Stelle das Programm hängen bleibt. Vielleicht kann ein Experte dem 
ansehen, wie man weiter vorgehen müßte.

Ich habe ein Testprogramm, wo zwei Konstante gelesen und auf dem 
Terminal ausgegeben werden.  Darin ist das fragliche Stück vom 
EEPROM-Leseprogramm eingefügt:

  byte i2c_eeprom_read_byte(  unsigned int eeaddress )
        {
           int deviceaddress = 0x50;
           byte rdata = 0xFF;
           Wire.beginTransmission(deviceaddress);
           Wire.send((int)(eepromaddress >> 8)); // MSB
           Wire.send((int)(eepromaddress & 0xFF)); // LSB
 ---> //   Wire.endTransmission();
 ---> //   Wire.requestFrom(deviceaddress,1);
           if (Wire.available()) rdata = Wire.receive();
           value1 = rdata;
Das Programm bleibt erst hängen, wenn ich eine der beiden markierten 
Stellen aktiviere. Sogar die Stelle Wire.beginTransmission(...) wird 
durchlaufen. Ich vermute, dort hat der Chip ein Ack gesendet. Ist 
allerdings ein Widerspruch zu meiner obigen Vermutung, daß TWI_READY 
nicht erfüllt sei.


> EEprom <-> Arduino: Sind die richtig verbunden? Mit Strom versorgt? Sind
> die Pins richtig eingestellt. Evtl mal Oszi anschliessen.
Diese normale Vorbedingung hatte ich in meiner Anfrage gar nicht erst 
erwähnt. Der Chip hat, was er braucht und auf der gleichen 
SDA/SCL-Schiene sitzt auch ein funktionierendes I2C-LCD.

Gruß
knut

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Alexander Schmeil schrieb:
> int deviceaddress = 0x50;

Schiebt die Arduino Software diese Adresse erst einmal nach rechts? Die 
normale Grundadresse für I2C EEPROMs liegt nämlich bei 0xA0, wenn alle 
Adresspins am EEPROM low sind. Das unterste Bit wird ja als R/W Marker 
benutzt, so das 0xA1 dann die Leseadresse wäre.

Alexander Schmeil schrieb:
> Der Chip hat, was er braucht und auf der gleichen
> SDA/SCL-Schiene sitzt auch ein funktionierendes I2C-LCD.

Ok, dann hast du ja ein Device, wo es zweifelsfrei feststeht. Check die 
Adresslage damit nochmal durch.

von Mike (Gast)


Lesenswert?

Matthias Sch. schrieb:
> Die normale Grundadresse für I2C EEPROMs liegt nämlich bei 0xA0
Die Standard I2C Adressen sind immer noch 7 Bit lang.
Was du meinst, ist wahrscheinlich das Steuer- bzw. Adressbyte, dass sich 
aus Adresse und Datenrichtungsbit zusammensetzt (aaaaaaad).

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

ha das kenne ich


beim senden des letzten Bytes darf keine akcnowabfrage erfolgen , sonst 
hängt sich das TWI interface auf.

beachte imfolgenden beispiel die letzten 3 zeilen
1
void rexeeprom(unsigned char bhigh, unsigned char blow, unsigned char bufferlen)
2
{    
3
delay_ms(10);
4
TWI_STARTCONDITION(); 
5
TWI_SLA_W (exteeprom_SLA_W);
6
TWI_SENDDATA (bhigh);
7
TWI_SENDDATA (blow);
8
TWI_RSTARTCONDITION(); 
9
TWI_SLA_R (exteeprom_SLA_R);
10
for (n=0;n<bufferlen-1;n++)
11
putchar1(TWI_RECIVEDATA_ACK ());
12
putchar1(TWI_RECIVEDATA_NACK ()); 
13
TWI_STOPCONDITION();  
14
}
hier noch die Funktionsdefinitionen

http://www.deviltronic.de/projekte/twi.pdf

von Alexander S. (knut740)


Lesenswert?

Winfried J. schrieb:
> beim senden des letzten Bytes darf keine akcnowabfrage erfolgen , sonst
> hängt sich das TWI interface auf.

Hi Winfried,
darauf deutet bei mir hin, daß die Zeile
 Wire.endTransmission();
dazu führt, daß mein Programm hängen bleibt. Als Konsequenz müßte ich 
allerdings die vorhandenen Wire.h/cpp bzw. twi.h/c umschreiben, was ich 
gern vermeiden würde - wegen der Fehler, die ich sicher machen würde und 
weil ich das dann bei jedem Update von Arduino-Libs bzw. WinAVR/gcc 
wiederholen müßte.

Eine andere Frage für meine weiteren Versuche hätte ich noch: Was steht 
in einem fabrikneuen EEPROM in den Speicherzellen? Null oder F?

Ich füge mal mein unaufgeräumtes Testprogramm bei, vielleicht habe ich 
irgendwelche Fehler drin, die man leicht beheben kann (letzter Versuch 
vor der Ochsentour).

Gruß
Alexander
1
// _07_I2C_EEPROM_ein_Wert_auslesen_Test1                             22. 11. 2013
2
//                                                                    14. 11. 2013
3
// zugöriges Programm:  _06_ein_SMT_einDat_I2C_EEPROM
4
5
// Ausgabe auf dem Terminal als milli-°C (wg. Excel!)
6
7
8
#include <EEPROM.h>
9
#include <Wire.h>
10
11
unsigned int eepromaddress = 0;
12
byte value1, value2 ;
13
int  value;
14
15
void setup()
16
{
17
     Serial.begin(9600);
18
     
19
     while (eepromaddress < 75)
20
       {
21
         byte rdata;
22
//         value1 = i2c_eeprom_read_byte(eepromaddress);
23
          Wire.beginTransmission(0x57);           // A0,A1,A2=on -->0x50, A0-A2=off --> 0x57 lt robot-Wiki
24
          delay(10);                                                // aus Forumsbeitrag abgeschrieben
25
          Wire.send((int)(eepromaddress >> 8)); // MSB
26
          Wire.send((int)(eepromaddress & 0xFF)); // LSB
27
//          Wire.endTransmission();                                 // hakt (immer)
28
          Wire.requestFrom(0x57,1);                                 // hakt 
29
          if (Wire.available()) rdata = Wire.receive();         
30
//        return rdata;        
31
          value1 = rdata;
32
//         value1 = 15;
33
         eepromaddress = eepromaddress + 1;
34
//         value2 = i2c_eeprom_read_byte(eepromaddress);
35
//         value2 =35;
36
         value2 = rdata;
37
         eepromaddress = eepromaddress + 1; 
38
         value = value1 << 8 | value2;
39
         Serial.print(eepromaddress, DEC);                         // hier wird irgend etwas geschrieben, zwecks 
40
         Serial.print("\t");                                       // Kontrolle, ob das Programm bis hierher kommt
41
         Serial.print(value1, DEC);
42
         Serial.print("\t");
43
         Serial.print(value2, DEC);
44
         Serial.print("\t"); 
45
         Serial.print(value, DEC);
46
         Serial.print("\t");        
47
         Serial.print("Text");         
48
49
         Serial.println();   
50
      }                                      //  Ende while......................
51
 
52
        delay(10);
53
   }                                         // Ende setup
54
55
56
57
void loop()
58
  {
59
  }
60
  
61
  //..............................................................................................
62
  
63
   byte i2c_eeprom_read_byte(  unsigned int eepromaddress )        // Original-Routine aus Robot-Wiki
64
      {
65
         int deviceaddress = 0x57;                // A0,A1,A2=on -->0x50, A0-A2=off --> 0x57 lt robot-Wiki
66
         byte rdata = 0xFF;
67
         Wire.beginTransmission(deviceaddress);
68
         Wire.send((int)(eepromaddress >> 8)); // MSB
69
         Wire.send((int)(eepromaddress & 0xFF)); // LSB
70
         Wire.endTransmission();
71
         Wire.requestFrom(deviceaddress,1);
72
         if (Wire.available()) rdata = Wire.receive();
73
//         return rdata;
74
         return 15;
75
      }

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.