- EEPROM írásának és olvasásának folyamata
- EEPROM használathoz szükséges regiszterek részletes leírása
- Példaprogramok
———————————————————————
Az ATMEga328 vezérlőben 1Kbyte EEPROM memóriát találunk. Ez roppant hasznos olyan adatok tárolására, melyeket szeretnénk a tápfeszültség kikapcsolásának ideje alatt is megőrizni. Az EEPROM működési elvéről itt található információ. Sajnos ennek a memória típusnak nagy hátránya, hogy az adatok írása rendkívül lassú, valamint az újra írások száma is erősen korlátozott, kb. 100 000. Az olvasásnak elvileg nincs korlátja. Elméletben az adatok megőrzésének is van időkorlátja, az adatlap alapján kb. 20 év. A program tárolására szolgáló flash memória hasonló elven működik, csak a szervezése más, blokkokban párhuzamosan lehet írni sok memória cellát így gyorsabb a folyamat. Viszont ez a memóriának már csak kb. 10 000 írást bír ki. Több általam már megismert vezérlőnél tapasztaltam, hogy az EEPROM memóriaterületet nem külön alakítják ki a vezérlőben, hanem a flash memória területéből „hasítják” ki. Az ATMega328 esetében azonban külön területet kapunk, így az itt található EEPROM kicsit tartósabb (100e írást bír ki). Ezen a memória területen belül minden egyes memória byte-ot külön tudunk megcímezni. Mint említettem, az adatok beírása egy memória byte-ba nagyon hosszú folyamat, kb. 3.4millisecundum ideig tart. Ez nem tűnik soknak, de a 1Kbyte memória megtöltése adatokkal kb. 4 másodperc. Jó hír, hogy az adatok visszaolvasása sokkal gyorsabb! Ha a felhasználói programban vannak olyan részek, melyek sok adatot írnak az EEPROM-ba és és a ~4 másodperc várakozás nem engedhető meg, akkor lehetőségünk van megszakítás használatára. Ekkor elindítjuk az írási folyamatot, és egy megszakítás keletkezik annak befejezésekor. 3.4 millisec alatt rengeteg utasítást tud végrehajtani a vezérlőnk!
Néhány kapcsolódó információ:
- Az adatlap további információkat tartalmaz az EEPROM (és a flash memória) SPI porton keresztüli, illetve párhuzamos programozásáról. Jelen leírás a felhasználói programból történő egyetlen byte írásáról illetve olvasásáról tartalmaz ismertetést.
- Kritikus lehet az adatok beírása közbeni tápfeszültség ingadozás, ami a beírt adatok sérülését okozhatja. Az EEPROM írásához egy minimális feszültségre van szükség. A belső Brown-out Detector (BOD) engedélyezésével megelőzhető ez a probléma. A BOD áramkör (ha engedélyezve van) belső reset-et generál, ha a tápfeszültség nem ér el egy meghatározott minimális szintet, illetve ha az alá csökken. Ha reset történik írási művelet közben, az írási művelet befejeződik, feltéve, hogy a tápfeszültség elegendő.
- A nem szándékos EEPROM-írások megelőzése érdekében speciális írási eljárást kell követni. Ennek részleteit lásd később.
- Az EEPROM olvasásakor a CPU négy órajelciklusra leáll, mielőtt a következő utasítás végrehajtásra kerül.
- Az EEPROM írásakor a CPU két órajelciklusra leáll, mielőtt a következő utasítás végrehajtásra kerül.
Egy kiválasztott EEPROM tároló cella (byte) írásához vagy olvasásához a vezérlő EEARH és EEARL regiszterében kell megadni a tároló cella címét. Írási művelet esetén EEDR regiszterbe kell beírni a tárolni kívánt adatot (byte-ot). Olvasás esetén ebből a regiszterből tudjuk majd kiolvasni az EEPROM cellából kiolvasott adatot. Azt, hogy írni vagy olvasni akarunk, illetve kérünk-e megszakítást az írás befejezését követően, az EECR regiszter megfelelő bitjeinek beállításával tudjuk elérni.
Az EEPROM írásához és olvasásához szükséges regiszterek:
EEARH és EEARL – Az EEPROM címregiszter
![](https://starduino.hu/wp-content/uploads/2025/01/image.png)
- 7:0 bit – EEPROM adat. Az EEPROM írási művelete esetében az EEDR regiszterbe kell beírni azt az adatot, amelyet az EEARH és EEARL regiszterben megadott címen tárolni (beírni) az EEPROM-ba. Az EEPROM olvasási művelet esetében az EEDR tartalmazza az EEARH és EEARL regiszterben megadott EEPROM címről kiolvasott adatot.
AZ írás vagy olvasás vagy törlés művelete az EECR regiszterben bizonyos bitek bebillentésével kezdődik el.
EECR – Az EEPROM kotroll regiszter
![](https://starduino.hu/wp-content/uploads/2025/01/image-1.png)
- 7:6 bitek – fenntartva. Ezek a bitek az ATmega48A/PA/88A/PA/168A/PA/328/P fenntartott bitjei, és mindig nullaként jelennek meg.
- 5., 4. bit – EEPM1 és EEPM0: EEPROM programozási mód bitek. Az EEPROM programozási mód bit beállítása határozza meg, hogy melyik programozási művelet indul el az EEPE bit bebillentésekor (egybe írásakor). Lehetőség van az adatok programozására egy összevont műveletben (a régi érték törlése és az új érték programozása), vagy a törlési és írási műveletek két külön műveletben történő elvégzésére. A különböző üzemmódokat és azok végrehajtási idejét az alábbi táblázat mutatja.
![](https://starduino.hu/wp-content/uploads/2025/01/image-2.png)
Amíg az EEPE bit egybe van állítva, az EEPM0 és EEPM1 bitek írása figyelmen kívül lesz hagyva. Reset esetén EEPM0 és EEPM1 bitek 0-ra állnak vissza, kivéve, ha az EEPROM írási művelet végrehajtással van elfoglalva.
- 3. bit – EERIE: EEPROM Ready megszakítás engedélyezése. Az EERIE bit bebillentése (egybe írása) lehetővé teszi az EEPROM Ready megszakítást, ha az SREG regiszterben a globális megszakítások engedélyezve vannak. Az EERIE bit törlése letiltja a megszakítást. Az EEPROM Ready megszakítás akkor jön étre, amikor az EEPE bit törlődik az EEPROM-ba írás befejezésekor. A megszakítás nem jön létre az EEPROM írása vagy flash programozás során.
- 2. bit – EEMPE: EEPROM Master írási engedélyezés. Az EEMPE bit határozza meg, hogy az EEPE bit egyesre állítása elindítja-e EEPROM írását. Ha az EEMPE be van állítva, az EEPE négy órajelcikluson belüli beállítása a az EEAR regiszterben található címre írja az EEDR regiszterben található adatot. Ha az EEMPE bit értéke nulla, az EEPE bit egybe írásának nincs hatása. Amikor az EEMPE bitet a felhasználói szoftver írja egyre, a hardver négy órajelciklus után törli a bitet, ha nem követi az EEPE egyesre írása. Az EEPROM írási eljárását lásd az EEPE-bit leírásában.
- 1. bit – EEPE: EEPROM írási engedélyezés. Az itt leírt folyamat azért került kialakításra, hogy megakadályozza az EEPROM adatok véletlen felülírását.Ha a cím és az adatok helyesen vannak beállítva, az EEPE-bitet egybe kell írni, hogy az értéket a hardver a megadott címen az EEPROM-ba beírja. Ezt megelőzően azonban az EEMPE bitet kell egybe írni, különben az EEPE bit egyesre állítása nem okozza az írási művelet elkezdését. Ráadásul a két művelet között mindössze négy órajelnyi idő áll rendelkezésére a felhasználói szoftvernek.
Az EEPROM-ba történő íráskor a következő eljárást kell követni (a 3. és 4. lépés sorrendje nem lényeges):
1. Várjon, amíg az EEPE bit nulla lesz. Ez azt jelenti, hogy befejeződött egy előző EEPROM-ba írá.
2. Várjon, amíg az SELFPRGEN bit az SPMCSR regiszterben nulla lesz.
Ez azt jelenti, hogy nincs folyamatban flash programozás bootloader-el
3. Írja be az EEPROM-címet az EEAR regiszterbe (opcionális).
4. Írja be az új adatot EEDR regiszterbe (opcionális).
5. Állítsuk az EEMPE bitet egyre, miközben az EEPE és az EECR biteket nullára állítjuk.
6. Az EEMPE beállítása után négy órajelcikluson belül állítsa az EEPE bitet egyre.
Az EEPROM nem programozható a CPU Flash memóriába történő írása közben. A szoftvernek ellenőriznie kell, hogy a Flash programozás befejeződött-e, mielőtt új EEPROM írást kezdeményezne. Az 2 lépésnek csak akkor van jelentősége, ha vezérlő bootloader-t tartalmaz, amely lehetővé teszi a CPU számára a Flash programozását. Ha a CPU soha nem frissíti a a flash memóriát, akkor a 2. lépés elhagyható.
Figyelmeztetés: Az 5. és 6. lépés közötti megszakítás történik, akkor az adat EEPROM-ba írása sikertelen lesz, mivel az EEPROM írási engedélyezése után (EEMPE bit beállítása) biztosan több órajel ciklus történik, mint négy. Ha az EEPROM-hoz hozzáférő megszakítási rutin megszakít egy másik EEPROM-hozzáférést, az EEAR vagy EEDR bitek módosulnak, ami a megszakított EEPROM-hozzáférés sikertelenségét okozza. A problémák elkerülése érdekében javasolt az SREG regiszterben a globális megszakítás tiltása a folyamat lépéseinek idejére („I” bit).
Az írási hozzáférési idő letelte után az EEPE-bitet hardver törli. A felhasználói szoftver lekérdezheti ezt a bitet, és megvárhatja a nullát, mielőtt a következő bájtot írná. Az EEPE törlése után a vezérlő két ciklusra leáll a következő utasítás végrehajtása előtt. - 0. bit – EERE: EEPROM olvasás engedélyezése. Az EERE bit bebillentése indítja el az adat kiolvasását az EEAR regiszter által meghatározott címről. Ha a helyes cím beállításra került az EEAR regiszterben, az EERE bitbe egyet kell írni az EEPROM olvasásának elindításához. Az EEPROM olvasás egy utasítást vesz igénybe, és a kért adatok azonnal rendelkezésre állnak. Az EEPROM olvasásakor a CPU négy ciklusra leáll, mielőtt a következő utasítás végrehajtásra kerül.
A felhasználónak az olvasási művelet megkezdése előtt le kell kérdeznie az EEPE-bitet. Ha írási művelet van folyamatban, sem az EEPROM olvasása, sem az EEAR regiszter módosítása nem lehetséges.
A kalibrált RC oszcillátor szolál az EEPROM hozzáférések időzítésére. A CPU-ról történő EEPROM-hozzáférés tipikus programozási ideje 3.3 mSec illetve 26,368 RC oszcillátor ciklus.
Példaprogramok
A következő példakódok egy C függvényt mutatnak be az EEPROM-ba való íráshoz. A példa feltételezi, hogy a megszakítás nem történik a végrehajtás közben (például a megszakítások globális letiltásával). A példa azt is feltételezik, hogy a bootloader nem végez flash programozást a végrehajtás közben. Ha ez lehetséges, akkor az EEPROM írási függvénynek is meg kell várnia a folyamatban lévő SPM parancs befejezését.
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) { while(EECR & (1<<EEPE)), //várakozás az előző EEPROM írás befejezésére EEAR = uiAddress; //az EEPROM cím beírása az EEAR regiszterbe EEDR = ucData; //adat beírása az EEDR regiszterbe EECR |= (1<<EEMPE); //az írás engedélyezés bit bebillentése EECR |= (1<<EEPE); //írás indítása az EEPE bit bebillentésével }
A következő kód C függvényt mutat be az EEPROM olvasásához. A példa feltételezik, hogy a megszakítás nem történik a végrehajtás során.
unsigned char EEPROM_read(unsigned int uiAddress) { while(EECR & (1<<EEPE)); // várakozás az előző EEPROM írás befejezésére EEAR = uiAddress; //az EEPROM cím beírása az EEAR regiszterbe EECR |= (1<<EERE); //olvasás elindítása EERE bit bebillentésével return EEDR; //a függvény visszatér a kiolvasott adattal }
A teljesség igénye nélkül nézzünk néhány példát arra is, amikor az Arduino fejlesztési környezetben használjuk a belső EEPROM-ot. Nyilván az alkotók már előre megírtak néhány függvényt, ami segít nekünk, nem kell megérteni a fent leírtakból szinte semmit, csak használni kell.
Az első lépés, hogy be kell emelnünk az előre megírt programkódot az „#include <EEPROM.h>” elhelyezésével a kódunk elején. Ezt követően már csak használni kell a rendelkezésre álló függvényeket. Az alábbi példa nagyon primitív, ha részletesebb információkra van szükség, akkor itt lehet részletgazdagabb példakódot találni.
#include <EEPROM.h> void setup() { Serial.begin(9600); //sorosportra fogjuk kiírni a futás eredményét EEPROM.write(0,15); //a 0 eeprom címre 15-öt írunk int v1=1234; EEPROM.put(1,v1); //ez a függvény kiírja a változó tartalmát az eepromba, annyi byte-ot használ fel //amennyi szükséges a változó típusához. byte v2; int v3; v2=EEPROM.read(0); //v2 változóbba visszaolvassuk a 0. címről az adatot (15) EEPROM.get(1,v3); //beolvassuk a v3 int típusú változóba az 1. címről az int értéket //a változó típusáról tudja a függvény, hogy hány byte-ot kell beolvasnia //és annak típusa szerint értelmeznie //kiírjuk a visszaolvasott eredményeket a soros monitorra Serial.println(v2); Serial.println(v3); } void loop() {}
A futás eredménye a soros monitoron:
15
1234