تعلم الوحدات · الدرس 2.25
الذاكرة (EEPROM)
العودة إلى الدروسحفظ البيانات دون طاقة
EEPROM اختصار Electrically Erasable Programmable Read-Only Memory، أي ذاكرة قابلة للبرمجة والمسح كهربائيًا. تحتفظ بالبيانات بعد انقطاع الطاقة؛ استخدمها لحفظ معاملات Arduino بعد الإطفاء.
تضم شرائح AVR ذاكرة (EEPROM)، وتوجد أيضًا شرائح خارجية. حجم UNO هو 1KB، و Mega2560 هو 4KB.
المكونات المطلوبة
- لوحة أردوينو (ELEGOO UNO R3) فقط.
لا تحتاج أسلاكًا لأن الذاكرة داخل الشريحة.
افتح ملف البرنامج EEPROM.ino من ملفات الدرس في بيئة Arduino IDE. بعد إتمام التوصيلات، وصّل لوحة أردوينو (UNO R3 Board) بالحاسوب بكابل توصيل (USB Cable)، ثم اضغط زر Upload (رفع) لنقل البرنامج إلى اللوحة وتشغيله عليها.
إذا تعذر نقل البرنامج إلى اللوحة، فراجع قسم «رفع البرنامج ومعالجة خطأ الاتصال» في الدرس 1.5 «وميض LED وإضافة المكتبات» للتحقق من اتصال USB واختيار نوع اللوحة والمنفذ التسلسلي في بيئة Arduino IDE.
الكتابة
تتحمل ذاكرة (EEPROM) نحو 100,000 دورة كتابة ومسح لكل موقع. تجنب الكتابة المتكررة غير الضرورية داخل loop(). تبدأ العناوين من 0، ويخزن كل عنوان بايتًا واحدًا. UNO و Leonardo لهما 1024 بايتًا وعناوين 0–1023؛ و Mega2560 لها 4096 بايتًا وعناوين 0–4095.
EEPROM.write(address, value);تكتب قيمة إلى العنوان. value من byte أو char بمدى 0–255؛ وأي قيمة أكبر تقطع إلى بايت. على Mega2560، يتراوح العنوان الصالح من 0 إلى 4095. تستغرق الكتابة نحو 3ms. الكتابة والمسح المستمران قد يتلفان الذاكرة سريعًا؛ استخدمهما عند الحاجة مع مراعاة التوقيت.
يعرض demo1 حفظ أحرف elegoo من company ثم قراءتها إلى company2.
القراءة وحفظ أنواع متعددة
EEPROM.read(address);تقرأ بايتًا من العنوان المحدد، بدءًا من 0، وتعيد byte. الموقع الممسوح الذي لم تُكتب إليه بيانات يعطي القيمة 255.
بعد تشغيل المثال على لوحة أردوينو (UNO R3 Board) تُحفظ البيانات في ذاكرتها. جرّب تعليق أسطر EEPROM.write في البرنامج، ثم اضغط Upload (رفع) في Arduino IDE لنقل النسخة المعدلة إلى اللوحة. ستقرأ البيانات نفسها حتى بعد إعادة ضبط اللوحة، وبذلك تتحقق من استمرارها بعد الإطفاء. افتح Serial Monitor، وراجع الدرس 2.4 «المراقب التسلسلي» لمعرفة طريقة فتحه وضبط سرعة الاتصال وقراءة البيانات.

تتعامل write() و read() مع بايت واحد مثل char أو byte. إذا كانت البيانات int أو float أو غيرهما أكبر من بايت، يجب قراءتها وكتابتها بايتًا بعد بايت لتجنب القطع. يعرض demo2 قالب دالة للقراءة والكتابة مع أنواع مختلفة، ويحفظ البيانات في union ثم يمر على تمثيلها البايتّي.
قوالب الدوال و union
template<typename T>يعلن template<typename T> قالب دالة بمعامل نوع اسمه T. عند استدعاء الدالة، يحدد المترجم النوع الفعلي، مثل int أو char أو float أو double، ويستخدمه لإنشاء نسخة مناسبة من الدالة.
union بنية يشترك أعضاء من أنواع مختلفة في مساحة الذاكرة نفسها، فيغطي أحدها تمثيل الآخر. يعرض الدرس عضوًا T my_type ومصفوفة char باسم charbuf في union data.
تخزن القيمة في my_type من نوعها، ثم تكتب charbuf بايتًا بعد بايت لأنها تشغل الذاكرة نفسها؛ وهذا يعادل حفظ التمثيل البايتّي لـ my_type. وتستخدم EEPROM_read الفكرة نفسها في الاتجاه المقابل.
الكود
EEPROM/demo1.ino
void test1 (void)
{
char company[7] = {"elegoo"};
char company2[7] = {"0"};
for(int i=0 ; i<6 ;i++ )
{
EEPROM.write(i,company[i]);
}
for(int i=0 ; i<6 ;i++ )
{
company2[i] = EEPROM.read(i);
}
Serial.print("company:");
Serial.println(company2);
Serial.println("***********************************************************");
}
EEPROM/demo2.ino
template<typename T>
void EEPROM_write(T data1,int address)
{
union data{
T my_type;
char charbuf[];
} data2;
data2.my_type=data1;
for(int i=address ; i<sizeof(data1) ;i++ )
{
EEPROM.write(i , data2.charbuf[i]);
}
}
template<typename T>
T EEPROM_read(T data ,int address)
{
union data{
T my_type;
char charbuf[];
} data2;
for(int i=address ; i<sizeof(T) ;i++ )
{
data2.charbuf[i] = EEPROM.read(i);
}
return data2.my_type;
}
EEPROM/EEPROM.ino
// ↑↑↑the Definition of demo1
// ↑↑ demo2
//www.elegoo.com
//2019.9.11
#include <EEPROM.h>
void setup()
{
Serial.begin(9600);
test1();
float a=3.14; //'a' is the data you want to store in eeprom
float a2=0; //'a2' is the data you want to read from eeprom
EEPROM_write(a,0); /* '0' is the address on eeprom
the range address on UNO eeprom:0~1023
you can store your data between 0 to 1023 you like */
Serial.print("float data:");
Serial.println(EEPROM_read(a2,0));
int b1=2000;
int b2=0;
EEPROM_write(b1,0);
Serial.print("int data:");
Serial.println(EEPROM_read(b2,0));
long c1=65539;
long c2=0;
EEPROM_write(c1,0);
Serial.print("long data:");
Serial.println(EEPROM_read(c2,0));
char d1[50]=__DATE__;
char d2[50]="0";
EEPROM_write(d1,0);
Serial.print("string data:\n elegoo:");
Serial.println(EEPROM_read(d2,0));
}
void loop()
{
}