Jak používat externí EEPROM

Zápisník experimentátora

Hierarchy: Externá EEPROM

V tomto článku si vysvětlíme, jak můžeme pracovat s externí EEPROM. Externí EEPROM se obvykle ovládají protokolem I2C a v tomto článku se budeme věnovat právě takovým EEPROM. Příklad bude pro 24LC16B, ale až na drobnosti bude tento návod univerzální pro libovolnou EEPROM.

Použité součástky

Na tento experiment stačí pouze pár součástek:

  • Arduino Pro Mini (link) - Použil jsem ho proto, že se vejde i na nejmenší zkušební pole.
  • Breadboard 400 Holes (link) - Na něm máme dost místa na dva mikrospínače.
  • Převodník CP2102 USB to Serial (link) - Převodník slouží k naprogramování Arduino.
  • Mikrospínače (linklink) - Potřebujeme dva kusy. Do zkušebního pole se dají použít i čtyřpinový i dvojpinové. Někdy jsou piny dlouhé, nebo mají podivné výstupky. Nebojte se ty konce odstřihnout, aby se lépe daly zastrčit.
  • EEPROM 24LC16B

Arduino je upraveno tak, že má na I2C (nachází se netradičně na extra pinech uprostřed Arduina) připájenou pin lištu s otvory, aby se pomocí dvou propojovacích vodičů dalo snadno propojit s EEPROM.

Dvě tlačítka se používají ke spuštění konkrétních testů a jsou připojeny na piny 6 a 8 na Arduinu. EEPROM je připojena k napájení a adresové piny A0, A1 a A2 jsou nezapojené. To platí ale pouze pro tento konkrétní typ EEPROM. Ostatní musí obvykle připojit tyto piny na GND nebo na VCC, čímž si nastaví I2C adresu. Je třeba si vždy zkontrolovat datasheet ke konkrétnímu typu a nastavit to podle něj.

Knižnice

Na ovládání EEPROM existuje dobrá knihovna extEEPROM. Nainstalujte si ji prostřednictvím správce knihoven.

Vzorový příklad

Při tvorbě tohoto vzorového příkladu jsem vyšel z toho, co je přiložen ke knihovně. V době psaní tohoto článku byl přiložen příklad s chybami. Proto se orientujte podle mého vzoru.

Příklad po spuštění vypíše obsah EEPROM a čeká na stisknutí tlačítka. Dvě tlačítka mohou vyvolat následující akci:

  • Tlačidlo 6 - Test zapisování. Test zaplní celou paměť postupně se zvyšujícími 32bitovými čísly. Potom vypíše obsah celé paměti.
  • Tlačidlo 8 - Test mazání. Test zaplní celou paměť hodnotou 0xFF. Potom vypíše obsah celé paměti.

Nebudu komentovat celý zdrojový kód, pouze jeho podstatné části. Funkce eeErase, eeWrite a eeRead jsem pouze mírně pozměnil vůči originálu a nacházejí se pouze v kompletních zdrojových textech.

Externí EEPROM 24LC16B dokáže uložit 2 kB 8-bitových hodnot. V tomto případě ji reprezentuje objekt eep. Chvíli mi trvalo, než jsem ze zdrojových textů uhodl, na co slouží parametr page size. Pro vás je důležitá informace, že tam třeba nechat vždy hodnotu 16. Je to velikost dat, které se dají najednou přepravit a velikost je limitována i možnostmi implementace I2C v Arduine.

#include <extEEPROM.h>

//One 24LC16B EEPROMs on the bus
const uint32_t totalKBytes = 2; // for read and write test functions
const uint8_t chunkSize = 4;    // this can be changed, but must be a multiple of 4 since we're writing 32-bit integers
extEEPROM eep(kbits_16, 1, 16); // device size, number of devices, page size

const uint8_t btnStart = 6;     // start button
const uint8_t btnErase = 8;     // erase button

Ve funkci setup nastavím dvě tlačítka jako vstupy a abych na zkušební pole nemusel dávat externí rezistory, jsou zde aktivovány interní pull-up rezistory. To znamená, že na daném pine naměříme hodnotu LOW pouze tehdy, když je mikrospínač stlačený. Sériový port je nastaven na hodnotu 115200, aby byly výpisy údajů rychlé. Po resetu Arduino se vypíše aktuální obsah EEPROM a legenda se seznamem funkcí.

void setup(void)
{
  pinMode(btnStart, INPUT_PULLUP);
  pinMode(btnErase, INPUT_PULLUP);
  Serial.begin(115200);
  uint8_t eepStatus = eep.begin(twiClock400kHz);      //go fast!
  if(eepStatus) {
    Serial.print(F("extEEPROM.begin() failed, status = "));
    Serial.println(eepStatus);
    while (1);
  }

  // dump current EEPROM memory
  dump(0,totalKBytes*1024);

  Serial.println(F(""));
  Serial.println(F("Press button '6' to start write test"));
  Serial.println(F("Press button '8' to start erase test"));
}

Funkce loop sleduje, zda jsme nestiskli nějaké tlačítko. Krátký delay slouží k ošetření zákmitů, ale v reálu trvá zapsání a vypsání údajů o něco déle a proto by tam volání funkce nemuselo být.

void loop(void)
{
if(digitalRead(btnStart) == LOW) {
  delay(100);
  eeWrite(chunkSize);
  eeRead(chunkSize);
  dump(0,totalKBytes*1024);
  }
 
if(digitalRead(btnErase) == LOW) {
  delay(100);
  eeErase(chunkSize,0,totalKBytes*1024);
  dump(0,totalKBytes*1024);
  }
}

Funkce dump slouží na kontrolní výpis údajů. Nepsal jsem ji, jen jsem na jejím konci opravil chyby, které zabraňovaly tomu, aby byl obsah paměti pěkně formátovaný. Líbí se mi, jak se její autor pokusil přehledně formátovat údaje. Pokuste se podle jejího kódu uhodnout, jak asi vypadají výsledné údaje.

void dump(uint32_t startAddr, uint32_t nBytes)
{
  Serial.print(F("EEPROM DUMP 0x"));
  Serial.print(startAddr, HEX);
  Serial.print(F(" 0x"));
  Serial.print(nBytes, HEX);
  Serial.print(F(" "));
  Serial.print(startAddr);
  Serial.print(F(" "));
  Serial.println(nBytes);
  uint32_t nRows = (nBytes + 15) >> 4;

  uint8_t d[16];
  for(uint32_t r = 0; r < nRows; r++) {
    uint32_t a = startAddr + 16 * r;
    eep.read(a, d, 16);
   
    Serial.print(F("0x"));
    if ( a < 16 * 16 * 16 ) Serial.print(F("0"));
    if ( a < 16 * 16 ) Serial.print(F("0"));
    if ( a < 16 ) Serial.print(F("0"));
    Serial.print(a, HEX); Serial.print(F(" "));
   
    for(int c = 0; c < 16; c++) {
      if(d[c] < 16)
        Serial.print(F("0"));
      Serial.print(d[c], HEX);
      Serial.print(c == 7 ? "  " : " ");
    }
    Serial.println(F(""));
  }
}

Pokud na to nemáte čas nebo článek čtete jen ze zvědavosti a nebudete si zapojení skládat, pak výstup funkce vypadá takto.

EPROM DUMP 0x0 0x800 0 2048
0x0000 00 00 00 00 00 00 00 01  00 00 00 02 00 00 00 03
0x0010 00 00 00 04 00 00 00 05  00 00 00 06 00 00 00 07
0x0020 00 00 00 08 00 00 00 09  00 00 00 0A 00 00 00 0B
0x0030 00 00 00 0C 00 00 00 0D  00 00 00 0E 00 00 00 0F

Toto byl krátký úvod ke používání externích EEPROM. V některém z následujících článků se na ukládání dat podíváme z praktické stránky a ukážeme si, jak ukládat i složitější údaje pohodlně a bezpečně.

Zdrojový kód

Zdrojový kód se nachází na GitHub.


21.06.2017


Menu