EEPROM írás-olvasás

Tanfolyamok, oktatások és kapcsolódó házi feladatok...
Válasz küldése
Petyperetty
DrótVégénSzéndarab
Hozzászólások: 18
Csatlakozott: 2017. március 19. vasárnap, 6:45

EEPROM írás-olvasás

Hozzászólás Szerző: Petyperetty »

Üdv Mindenkinek! Talán már van ilyen téma, én nem találtam meg. Bocsi, ha benéztem!

Ismerkedek az I2C kommunikációval egy EEPROM programozásán keresztül. A céláramköröm a 24LC32.
Leprogramoztam az első 100 memóriacím írását-olvasását. Eredményül azt kaptam, amiért írok és nem értem.
Csatoltam egy képet és a kódot. Tudna valaki segíteni hol rontottam el?

https://drive.google.com/open?id=0B_BT0 ... W40RVZUeEE

Kód: Egész kijelölése

#include "Wire.h"
#define eeprom1 0x57

void setup() 
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  int addr=0;
  for(addr=0;addr<=100;addr++)
  {
   Wire.beginTransmission(eeprom1);
   Wire.write(int (addr >> 8));
   Wire.write(int (addr & 0xFF));
   Wire.write(128);
   Wire.endTransmission();
   Serial.print(addr,HEX);
   Serial.print(": ");
   Wire.beginTransmission(eeprom1);
   Wire.write(int (addr >> 8));
   Wire.write(int (addr & 0xFF));
   Wire.endTransmission();
   Wire.requestFrom(addr,1);
   if (Wire.available())
    {
      Serial.print(Wire.read());
      Serial.print("\t");
      Serial.print("\t");
    }
    else Serial.print("no received data");
  if(addr%4==0)
    Serial.println();
    else Serial.print("\t"); 
  }
  while(1)
  {
    delay(1);
  }
}
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: kapu48 »

Kód: Egész kijelölése

Nem kel újra az int az: Wire.write(int (addr >> 8)); utasításba.
Mert így mindig új változót hozol létre.
Elég csak int nélkül: Wire.write(addr >> 8); // Lesz automatikus tipus modosítás

Vagy még jobb ha, végrehajtasz típus módosítást byte-re. Mivel addr eredetileg int, de te felbontod 2 Byte-re.:
Wire.write((byte)addr >> 8);
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: kapu48 »

Nem jó, az int addr ! Értékhatára: https://www.arduino.cc/en/Reference/Int
-32,768 to 32,767
Mert 32767-nél nagyobb címet minuszként értelmez, És mivel címzésnél nem használunk minusz értéket, ezért jobb lenne az:
unsigned int addr;
Petyperetty
DrótVégénSzéndarab
Hozzászólások: 18
Csatlakozott: 2017. március 19. vasárnap, 6:45

Re: EEPROM írás-olvasás

Hozzászólás Szerző: Petyperetty »

Jogos, de sajnos nem segít. Semmi változás. Viszont a 0x57 -es címre be tud írni.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: Robert »

Tipp:

Kód: Egész kijelölése

Wire.beginTransmission(eeprom1);
   Wire.write(int (addr >> 8));
   Wire.write(int (addr & 0xFF));
   Wire.endTransmission(); 
   Wire.requestFrom(addr,1); <- az írás / olvasási címed nem jó és/vagy a kommunikáció kezelésed nem jó.
Amit én használok (Arduino-0023):

Kód: Egész kijelölése

#include <Wire.h> //Include the Arduino I2C Library</pre>



void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
int rdata = data;

Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // MSB
Wire.send((int)(eeaddress & 0xFF)); // LSB

Wire.send(rdata);

Wire.endTransmission();
}

void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddresspage >> 8)); // MSB
Wire.send((int)(eeaddresspage & 0xFF)); // LSB

byte c;
for ( c = 0; c < length; c++)
Wire.send(data[c]);

Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
byte rdata = 0xFF;

Wire.beginTransmission(deviceaddress);
Wire.send((int)(eeaddress >> 8)); // MSB
Wire.send((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);

if (Wire.available()) rdata = Wire.receive();

return rdata;
}

void setup() {
char somedata[] = "dayzlab.wordpress.com"; //Data
Wire.begin(); //Start I2C connections
Serial.begin(9600);
i2c_eeprom_write_page(80, 0, (byte *)somedata, sizeof(somedata)); // write to EEPROM

delay(10); //add a small delay

Serial.println("Memory written");
}

void loop() {
int addr=0; //EEPROM Address 0
byte b = i2c_eeprom_read_byte(80, 0); // access the first address from the memory

while (b!=0) {
  Serial.print("T");
Serial.print((char)b); //print content to serial port
addr++; //increase address
b = i2c_eeprom_read_byte(80, addr); //access an address from the memory
}

Serial.println(" ");
delay(2000);
}
Ill magyarázattal:
http://www.hobbytronics.co.uk/arduino-external-eeprom
http://www.tavir.hu - a gazda :)
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: SzLacus »

Szerintem azért nem működik, mert az addr a ciklus változód, és azzal manipulálsz a cím előállításánál is.
Mi is történik?
Létre hozod a ciklusváltozódat a ciklus előtt int-ként, nulla értékket rendelve hozzá.
Aztán a ciklust felépíted, megint nulla értékadással az addr változónak, feltételként adod, hogy amíg kisebb egyenlő 100, (ennyiszer akarod végrehajtani), és jelölöd, hogy egyesével növekedjen a ciklus számláló.
Ez eddig rendben van. Elkezded a kommunikációt az adott című eszközzel. Ez után ki kell kiküldened a felső, majd az alsó felét a címnek, utána pedig az adatot amit az előbb kiküldött címre akarsz beírni. Az odáig rendben van, hogy egy 2 bájtos int felső felét jobbra shifteléssel kapjuk, az alsót pedig 0xFF maszkolással. De te ezt a ciklusváltozóddal teszedmeg.
Az első körben a ciklusváltozót jobbra lököd 8-al, rögtön el is tűnik az alja, pedig a címzés ott fog növekedni 100-ig. Mivel int-ként lett létre hozva felülről 1-esek fognak belépni a jobbra léptetéssel. Nem akarom végig követni lépésenként, hogy kiderüljön 57-re és 3C-re miért van értelmes adat a küldött képen, de szerintem az a probléma gyökere, hogy a ciklusváltozódat két helyen maacerálod.
Megoldás több is lehet, egynek az is jó, ha ideiglenes bájt méretű változóba másolod minden ciklusnál az addr felső, majd az alsó felét, és azt adod a wire hívásban címnek.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: kapu48 »

Kód: Egész kijelölése

Ha: (addr >> 8)
Szerintem nincsen =-ség adás definiálva, ilyenkor bekerül a belső regiszterbe a változó, és ott hajtódik végre a művelet.
Aminek az eredménye kerül továbbításra

Ha így lenne: addr >>= 8; akkor lenne neked igazad.
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: kapu48 »

Kód: Egész kijelölése

Más!
unsigned int eeaddress-t Konvertálni int-re teljesen értelmetlen.
Wire.send((int)???(eeaddress >> 8)); // MSB
Föleg, hogy a Wire.send(byte-t vár);

https://www.arduino.cc/en/Reference/WireSend
Petyperetty
DrótVégénSzéndarab
Hozzászólások: 18
Csatlakozott: 2017. március 19. vasárnap, 6:45

Re: EEPROM írás-olvasás

Hozzászólás Szerző: Petyperetty »

Megvilágosodtam! Megoldottam a problémát. :-) Rájöttem, hogy SzLacus -nak van igazsága az ügyben. Marhaság volt a címet használni ciklusszámlálónak is. Pláne, hogy mindenféle shift-elgetéssel, meg maszkolgatással babráltam.
Azt találtam ki, hogy ha már byte szervezés, akkor legyen szétválasztva rendesen byte-okra. Létrehoztam egy külön ciklus számlálót, külön egy változót a felső címnek és külön egy változót az alsó címnek. Ezután már rendesen szétválasztva és sorrendbe rendezve elkezdett működni a forráskód.
Amit még nem értek, hogy vajon az első három memóriacímről miért nincsen adat és a negyedik miért ad vissza 255-öt?

https://drive.google.com/open?id=0B_BT0 ... lgxR0RSWFk

Kód: Egész kijelölése

#include "Wire.h"
#define eeprom1 0x57

void setup() 
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
byte i,MSB=0,LSB=0;
  for(i=0;i<=100;i++)
  {
   Wire.beginTransmission(eeprom1);
   Wire.write(MSB);
   Wire.write(LSB);
   Wire.write(34);
   Wire.endTransmission();
   if(i<16) Serial.print("0");
   Serial.print(i,HEX);
   Serial.print(": ");
   Wire.beginTransmission(eeprom1);
   Wire.write(MSB);
   Wire.write(LSB);
   Wire.endTransmission();
   Wire.requestFrom(eeprom1,1);
   if(Wire.available())
    {
      Serial.print(Wire.read());
      Serial.print("\t");
      Serial.print("\t");
    }
    else Serial.print("no received data");
  if(i%4==0)
    Serial.println();
    else Serial.print("\t"); 
  MSB++;
  LSB++;
  }
  while(1)
  {
    delay(1);
  }
}
Avatar
SzLacus
Tranzisztorgyógyász
Hozzászólások: 175
Csatlakozott: 2012. május 20. vasárnap, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: SzLacus »

Azzal, hogy a loop elején hozod létre az MSB és LSB változódat, azt éred el, hogy minden kanyarban nullával jön létre.
Lejátszod a wire dolgokat, meg a kiírásokat, aztán növeled a cím mindkét felét. De ez így nem lesz jó, én azt nem értem, mitől működik. Pontosabban 100-ig az alsó fele jől számo, sőt 255ig is jól számolna, de a felső fél csa ez itán növekedhetne egyet, és minden 255 után újra és újra.
Ugyanis a felső címfelet csak akkor szabadna növelned, ha az alsó túlcsordul, mert ugye ez egy számot ábrázol két bájton.
Én azt csinálnám, hogy a ciklusváltozó az lehetne uint, egy bájt pedig felvenné hol a felső, hol az alsó felének az értékét, és ez menne a wire.send-be, a cím kiküldésekor. A szétválasztásra pedig használnám a highbyte() és a lowbyte() függvényeket, hiszen ezeket erre hozták létre.
Azt biztosan észrevetted, hogy 101 alkalommal fut a ciklusod, és a 0 címről származó külön sorban elöl szerepel. Ha nem így akartad, akkor a kulcs a ciklusváltozó feltétel részében van. A kiírás feltételekén szabott egyenlőség a másik kulcs.
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: csabeszq »

A fenti kódodban nem látom a delay-eket (EEPROM).

Az EEPROM úgy megy, hogy beírsz valamit, aztán tetű lassan befejezi. Ameddig az EEPROM ír, addig eltűnik az I2C buszról, tehát NACK-kal válaszol minden további kérésre. A Wire library-t meg olyan hiperintelligensen írták meg, hogy nem tudja, mi az az I2C NACK. Sok szar kódot láttam már életemben, de a Wire-t nehéz alulmúlni. Nem véletlen nem használom.

Nyomhatod ezerrel a kéréseket, ha túl gyorsan jönnek, az EEPROM NACK-kal fog válaszolni, a Wire meg leszarja, hogy mit küld az EEPROM vissza, meg hogy éppen elérhető-e vagy írással van elfoglalva.

Hivatalosan a doksiban 5ms / page szerepel írási időként a 24LC32-ben. Durván túltolod.
Petyperetty
DrótVégénSzéndarab
Hozzászólások: 18
Csatlakozott: 2017. március 19. vasárnap, 6:45

Re: EEPROM írás-olvasás

Hozzászólás Szerző: Petyperetty »

Értem, ez igaz akkor is, ha byte címzést használok, vagy csak a page szervezésre vonatkozik?
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: csabeszq »

Az EEPROM szerintem page-ekbe van szervezve. Ha 1 byte-ot írsz, akkor is 1 page lesz frissítve.

A neten mindig delay(5) van. Ha gyorsítani szeretnél, akkor ne egyesével küldd.
Petyperetty
DrótVégénSzéndarab
Hozzászólások: 18
Csatlakozott: 2017. március 19. vasárnap, 6:45

Re: EEPROM írás-olvasás

Hozzászólás Szerző: Petyperetty »

Bejött! Szuper lecke volt ez nekem, köszönöm! 3us várakozást írtam be a beírás-kiolvasás közé és most teljesen jól működik.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: EEPROM írás-olvasás

Hozzászólás Szerző: Robert »

Pl. a 24LC512 esetén a lap írás 5msec! (4. oldal)
Nem 3 microsec!!!

http://ww1.microchip.com/downloads/en/D ... 21754M.pdf
http://www.tavir.hu - a gazda :)
Válasz küldése