Lekce 18 - Arduino a externí EEPROM přes I2C

11.05.2013 15:15

Translate to English

V minulém díle jsme si ukázali jak využít vestavěnou pamět EEPROM v Arduinu. Dnes si ukážeme jak připojit přes I2C rozhraní (2-vodičové) přívě libovolnou seriovou pamět EEPROM.

Já jsem si tedy pro naše pokusy sehnal několik pamětí. Jedná se o tyto kousky:

Typ EEPROM paměť cena cca datasheet
24C01 125 x 8bitů (1kbit)   4,40 Kč zde
24C08 1000 x 8bitů (8kbit) 1kB 7,30 Kč zde
24C32 4 096 x 8bitů (32kb) 4,096kB 11,10 Kč zde
24C128 16 384x 8 bitů  27,70 Kč zde 

My si teď ukážeme nejdříve jak pamět připojit k Arduinu. Není to složité stačí nám pouze napájení z Arduina a dva vodiče s SLA a SLC (I2C rozhraní) napojené na v případě Arduino UNO na A4 a A5. Plánek zapojení je zde:

V mém zapojení jsem vynechal kondenzátor 100nF zapojený mezi zem a napájení. Pokud chcete můžete jej tam dát, ale ať jsem hledal jak jsem hledal, účel a nutnost jej použít jsem nenašel. Jak můžete vidět vývody 1, 2 a 3 z EEPROM jsou takzvané adresovací vývody. To znamená, že když jsou všechny A0 až A2 připojeny k zemi, je adresa paměti 0x50. Když nějaký ten pin připojíte na +5V tak se adresa paměti změní - viz následující tabulka:

A2 A1 A0 adresa
GND GND GND 0x50
GND GND +5V 0x51
GND +5V GND 0x52
GND +5V +5V 0x53
+5V GND GND 0x54
+5V GND +5V 0x55
+5V +5V GND 0x56
+5V +5V +5V 0x57

 

My ale v zapojení nebude nic měnit a ponecháme adresu na 0x50 tím, že bude A0 až A2 zapojen k zemi. Vývod 4 z EEPROM je  také zem a vývod 8 je připojen k napájecímu napětí +5V. Vývod 7 z EEPROM je WP (write protection), tzv. pojistka proti zápisu, tu máme připojenu k +5V a je umožněno na paměť zapisovat. Když to bude naopak ke GND (zemi) toto umožneno nebude. Vývod 5 (SDA) připojíme na Arduino na I2C rozhraní, kde je na vývodu A4 (analogový pin4) a vývod 6 (SCL) na A5. Pokud vše máme zapojeno můžeme Arduino naprogramovat (Program je určen pro 24C01 nebo 24C02 - později vysvětlím):

Jak můžete vidět v okomentovaném kódu, je potřeba načíst knihovnu pro práci s rozhraním I2C a to wire.h. Zápis je jednoduchý. Nejdříve inicializujeme komunikaci s adresou zařízení 0x50 (můžeme i změnit), dále odešleme adresu v paměti (byte) u nás "5" a jako další byte odešleme naše data - pro test jsme zvolili číslo 222. 

Po zapnutí Serial Monitoru, musíme vidět prostě tohle:

Tak nám to funguje a zkusíme zapojit teď 24c08. No chvilka napětí a výsledek ten samý, na Serial Monitoru se objevilo číslo 222. Tak třetí pokus 24C128 - skoro Mercedes mezi EEPROM, 4kB paměti :-). A program na Serial vypsal hodnotu 255. Co se stalo? Proč to nefunguje?

Vysvetlení je jednoduché  a spočívá v adresování paměti v EEPROM. Když se koukneme do dokumentace k pamětím 24C01 a 24C08, tak k adresování jednotlivých bytes tak po nás byla vyžadována jedna hodnota (word) a u paměti 24C32 a 24C128, takže chyba je způsobena špatnou adresací. Program si upravíme tak, aby odeslal adresu na dvakrát. Jak si můžete prohlédnout zde:

V kódu jsem již odeslání hodnoty a získání integroval do funkce, aby byl kód přehlednější. Použil jsem zrovna 24C32 takže jsem mohl použít maximální adresu 4095, protože má kapacitu 4096 x 8 bitů a první adresa již začíná na 0. Já jsem na adresu 2574 odeslal hodnotu 147 a jak můžete vidět poté po spuštění serial monitoru, hodnota přečtené z téže adresy je v pořádku. :-)

V případě 24C128  je kapacita 16384 x 8 bitů tak poslední adresa je 16383. Když náhodou zkusíte překročit kapacitu a adresujete byte nějak za maximálná hranici EEPROM záčíná adresovat opět od začátku. Např. adresa u 24C32 maximální použitelná je 4095, ale když u této paměti budeme adresovat např. 4098 byte se zapíše nebo přečte z adresy 2.

Tak já myslíš, že pro vysvětlení EEPROM s použitím I2C to stačí. Ukládat jiné hodnoty jsme se naučili rozkladem na bytes v předchozím tutoriálu a ukládání textů je téměř shodné jako u interní EEPROM. Video nepřikládám, nebylo moc co točit :-) 

 

Zpět

Diskusní téma: Lekce 18 - Arduino a externí EEPROM přes I2C

Datum
Vložil
Titulek

uff

ten, kdo nevi, proc je tam ten kondik, ten by si nemel hrat s dratecky a mikroprocesory.. uff ta nova generace!

Datum
Vložil
Titulek

Re: uff

Kritizovat umí každý, ale vysvětlit, to už ne, že?

Datum
Vložil
Titulek

24C32

Mě s 24C32 funguje toto:

// funkce zápis byte
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
int rdata = data;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.write(rdata);
Wire.endTransmission();
}

// funkce čtení byte
byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
byte rdata = 0xFF;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);
if (Wire.available()) rdata = Wire.read();
return rdata;
}

Datum
Vložil
Titulek

24C01 Nefunguje

Přepsal jsem si ten 1 program a nefunguje to v serial monitoru mi to vypíše 255. Program jsem zkoušel i překopírovat a dělá to to samé. Proč?

Datum
Vložil
Titulek

Re: 24C01 Nefunguje

WP musí být připojeno na GND. Potom je umožněn zápis. Po připojení na 5V je zápis zakázán. V textu to je obráceně.

Datum
Vložil
Titulek

Zápis do celé EEPROM 24C16

Problém vyřešen - paměť 24C16 je uvnitř rozdělená do osmi oddílů po 256 bytech a ty se přepínají adresou zařízení, vývody A0, A1 a A2 nejsou zapojené a nefungují. Adresa 0x50 je pro zápis do prvního oddílu, 0x51 do druhého ....... a 0x57 je pro zápis do poslední části paměti. Odzkoušen zápis přes Arduino do celé paměti 24C16 a paměť pak přečtena v programátoru, funguje to.

Datum
Vložil
Titulek

Adresace jen prvních 256B

Vyzkoušel jsem program pro zápis do 24C01 a 24C02 s pamětí 24C16 a dopadlo to tak, jak jsem čekal - zapisuje jen do prvních 256B, takže při adrese 1999 zapíše data na adresu 207, protože do 8 bitů se tak velké číslo nevejde. Jak by se dalo zapisovat do celé paměti 24C16 (také 24C04 a 24C08)?

Datum
Vložil
Titulek

i2c eeprom zápis int hodnoty

je tedy správně toto? pro 24c32 a větší

void i2c_eepromIntWrite( int device, unsigned int adresa, int hodnota )
{
byte byte1 = hodnota;
byte byte2 = hodnota >> 8;
Wire.beginTransmission(device);
Wire.write((int)(adresa)); // odešle vyšší byte
Wire.write((int)(adresa & 0xFF)); // odešle nižší byte
Wire.write(byte1);
Wire.write(byte2);
Wire.endTransmission();
}

int i2c_eepromIntRead( int device, unsigned int adresa )
{
byte rdata1;
byte rdata2;
Wire.beginTransmission(device);
Wire.write((int)(adresa)); // odešle vyšší byte
Wire.write((int)(adresa & 0xFF)); // odešle nižší byte
Wire.endTransmission();
Wire.requestFrom(device,2);
if (Wire.available()) rdata1 = Wire.read();
if (Wire.available()) rdata2 = Wire.read();
return (rdata1+(rdata2 << 8));
}

Vyhledávání

arduino8.cz © 2015 Všechna práva vyhrazena.