شاید تا به حال در پروژه های مختلف به این نتجیه رسیده اید که مقدار برخی از متغیر ها بایستی حتی بعد از قطع شدن برق نیز باقی بماند. راه های مختلفی برای این کار وجود دارد. برای مثال استفاده از باتری بکاپ یا ذخیره اطلاعات بر روی ایسی های حافظه و یا حتی کارت SD از جمله راه های ذخیره اطلاعات بعد از قطع شدن برق است. اما بردهای آردوینو ذخیره اطلاعات را پس از قطع برق را برای ما بسیار ساده تر کرده اند. غیر از حافظه Flash و RAM در برخی میکروکنترلر ها حافظه دیگری با نام EEPROM قرار دارد. که اطلاعات موجود در این حافظه پس از قطع برق نیز باقی خواهد ماند. در این آموزش، همانند سلسله آموزش های تحلیل کتابخانه، به تشریح و تحلیل توابع کتابخانه EEPROM.h می پردازیم. در ادامه با مرجع تخصصی آردوینو به زبان فارسی، دیجی اسپارک همراه باشید.
حافظه EEPROM
کلمه EEPROM مخفف عبارت Electrically Erasable Programmable Read-Only Memory به معنای حافظه فقط خواندنی قابل برنامه ریزی و پاکسازی بصورت الکتریکی است. این نوع حافظه نوع پیشرفته تری از حافظه EPROM است. همانطور که گفته شد مقادیری که در این حافظه ذخیره شوند با قطع شدن تغذیه برد آردوینو از بین نمیروند و پس از روشن شدن مجدد، مقداری که قبل از قطع شدن تغذیه در آن ذخیره شده بود را همچنان خواهند داشت. مقدار حافظه EEPROM در برد های مختلف متفاوت است. با توجه به تصویر زیر میتوانید مقدار حافظه EEPROM برد آردوینو خود را مشاهده کنید.
یکی از نکته های مهم در حافظه های EEPROM که بایستی به آن توجه شود این است که این نوع حافظه دارای عمر مفید است. برای مثال حافظه EEPROM در میکروکنترلر های AVR دارای عمر مفید صد هزار بار نوشتن است.
نکات فنی کتابخانه EEPROM.h
کتابخانه EEPROM.h برای تعامل با فضای ذخیره سازی غیر فرار در برد های آردوینو مبتنی بر تراشه های AVR است. این کتابخانه با توابع ساده و روان رابط کاربری ساده ای را برای ارتباط با حافظه غیر فرار میکروکنترلر، فراهم میکند. این کتابخانه نیاز به نصب ندارد و جزء کتابخانه های پیش فرضی است که همراه نرمافزار آردوینو نصب میشود. برای درسترسی به سورس های این کتابخانه میتوانید در سیستم های تحت سیستم عامل ویندوز به آدرس زیر مراجعه کنید.
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM
برای استفاده از این کتابخانه نیاز است که فایل هدر مربوط به این کتابخانه را به کد خود اضافه کنید. همانند دستور زیر:
#include <EEPROM.h> void setup(){ } void loop(){ }
توابع کلیدی کتابخانه EEPROM.h
در این بخش توابع مهم و کلیدی کتابخانه را مورد بررسی قرار میدهیم. این کتابانه دارای توابع مختلفی است که هر یک از این توابع عملیات خاصی مثل نوشتن داخل حافظه EEPROM و یا خواندن از این حافظه را انجام می دهند. در ادامه با کاربرد هر یک از این توابه آشنا میشویم.
-
()read
این تابع برای خواندن یک بایت از یک آدرس مشخص در حافظه EEPROM است. ایت تابع دارای یک ورودی از نوع int است. این ورودی مکان مورد نظر در حافظه که قصد خواندن آن را دارید را مشخص میکند. شروع آدرس از عدد ۰ است. خروجی این تابع یک بایت است. که از آدرس مشخص شده در حافظه EEPROM خوانده شده است. در مثال زیر متغیر a ورودی تابع است و متغییر value خروجی تابع است.
value = EEPROM.read(a);
-
()write
تابع write همانطور که از نامش مشخص است برای نوشتن یک بایت عدد داخل حافظه EEPROM است. این تابع دارای دو ورودی است. ورودی اول همانند ورودی تابع read برای مشخص کردن آدرس است که از نوع int است. ورودی دوم مقداری است که قصد داریم آن را در حافظه EEPROM ذخیره کنیم. زمان مورد نیاز برای تکمیل نوشتن در حافظه EEPROM برابر ۳٫۳ میلی ثانیه است. پس برای نوشتن داخل این حافظه بایستی حداقل ۳٫۳ میلی ثانیه در برنامه خود تاخیر ایجاد کنید. در مثال زیر متغیر i مربوط به آدرس و متغیر value مقداری است که قصد ذخیره آن را داریم.
EEPROM.write(i, value);
-
()update
عملکرد تابع update همانند تابع write است. این تابع هم برای نوشتن در حافظه EEPROM استفاده میشود. ورودی های این تابع نیز همانند تابع write است. اما تفاوت این تابع با تابع write این است که این تابع تنها زمانی عملیات نوشتن در حافظه EEPROM را انجام میدهد که مقدار جدید برای نوشتن با مقدار ذخیره شده در آدرس مورد نظر متفاوت باشد. در مثال زیر عدد ۱۲ تنها یک بار در آدرس ۳ ذخیره خواهد شد و در ۲۵۴ مرحله دیگر حلقه این تابع عملیات نوشتن را انجام نمیدهد. این نوع عملکرد باعث می شود عمر مفید این حافظه مدت زمان طولانی تری باقی بماند.
for (int i = 0; i < 255; i++) { // write value "12" to cell 3 only the first time // will not write the cell the remaining 254 times EEPROM.update(3, 12); }
-
()get
تابع get همانند تابع read عملیات خواندن از حافظه EEPROM را انجام میدهد. تفاوت این تابع با تابع read این است که با استفاده از این تابع میتوانید هر نوع داده با هر مقداری را از حافظه EEPROM بخوانید. این تابع دارای دو ورودی است. ورودی اول از نوع int است که برای مشخص کردن آدرس مورد نظر برای شروع خواندن از حافظه EEPROM استفاده می شود. ورودی دوم میتواند float یا هر نوع دیگری که به آن معرفی میکنید، خروجی دهد. برای درک بهتر این مطلب یه مثال زیر توجه کنید.
float f = 0.00f; //Variable to store data read from EEPROM. int eeAddress = 0; //EEPROM address to start reading from //Get the float data from the EEPROM at position 'eeAddress' EEPROM.get( eeAddress, f );
-
()put
عملکرد تابع put همانند تابع write و update است. با این تفاوت که با استفاده از این تابع میتواند هر نوع داده ای را داخل EEPROM ذخیره کنید. این تابع دارای دو ورودی است. ورودی اول از نوع int است که برای مشخص کردن آدرس مورد نظر برای شروع نوشتن در حافظه EEPROM استفاده می شود. ورودی دوم میتواند float یا هر نوع دیگری که به آن معرفی میکنید، عملیات ذخیره سازی را انجام دهد. این تابع داخل خود از تابع update برای ذخیره سازی استفاده کند. بنابراین تا زمانی که تغیرری در داده ایجاد نشود این تابع عملیات نوشتن را انجام نخواهد داد. برای درک بهتر این مطلب یه مثال زیر توجه کنید.
float f = 123.456f; //Variable to store in EEPROM. int eeAddress = 0; //Location we want the data to be put. //One simple call, with the address first and the object second. EEPROM.put(eeAddress, f);
-
[]EEOROM
این اپراتور مانند یک آرایه از شناسه `EEPROM` استفاده می کند. سلولهای EEPROM را می توان مستقیماً با استفاده از این روش خواند و نوشت. برای درک بهتر این مطلب یه مثال زیر توجه کنید.
//Read first EEPROM cell. val = EEPROM[ 0 ]; //Write first EEPROM cell. EEPROM[ 0 ] = val; //Compare contents if( val == EEPROM[ 0 ] ){ //Do something... }
اجرای نمونه برنامه
در این قسمت سه نمونه برنامه، برای خواندن و نوشتن داخل حافظه EEPROM و همچنین پاک کردن مقادیر ذخیره شده در این حافظه، قرار داده شده است. در کد اول مقدار ورودی آنالوگ A0 خوانده شده و در حافظه EEPROM ذخیره می شود. در این کد از تابع write برای ذخیره سازی مقدار ورودی آنالوگ استفاده شده است. همچنین پورت سریال برای گزارش وضعیت فعال شده است.
/* EEPROM Write Stores values read from analog input 0 into the EEPROM. These values will stay in the EEPROM when the board is turned off and may be retrieved later by another sketch. */ #include <EEPROM.h> // the current address in the EEPROM (i.e. which byte // we're going to write to next) int addr = 0; void setup() { Serial.begin(115200); EEPROM.begin(512); } void loop() { // need to divide by 4 because analog inputs range from // ۰ to 1023 and each byte of the EEPROM can only hold a // value from 0 to 255. int val = analogRead(A0) / 4; // write the value to the appropriate byte of the EEPROM. // these values will remain there when the board is // turned off. EEPROM.write(addr, val); // advance to the next address. there are 512 bytes in // the EEPROM, so go back to 0 when we hit 512. // save all changes to the flash. addr = addr + 1; if (addr == 512) { addr = 0; if (EEPROM.commit()) { Serial.println("EEPROM successfully committed"); } else { Serial.println("ERROR! EEPROM commit failed"); } } delay(100); }
در کد دوم از آدرس ۰ تا ۵۱۲ حافظه EEPROM توسط تابع read خوانده شده و در سریال مانیتور نمایش داده میشود.
/* EEPROM Read Reads the value of each byte of the EEPROM and prints it to the computer. This example code is in the public domain. */ #include <EEPROM.h> // start reading from the first byte (address 0) of the EEPROM int address = 0; byte value; void setup() { // initialize serial and wait for port to open: Serial.begin(115200); EEPROM.begin(512); } void loop() { // read a byte from the current address of the EEPROM value = EEPROM.read(address); Serial.print(address); Serial.print("\t"); Serial.print(value, DEC); Serial.println(); // advance to the next address of the EEPROM address = address + 1; // there are only 512 bytes of EEPROM, from 0 to 511, so if we're // on address 512, wrap around to address 0 if (address == 512) { address = 0; } delay(500); }
در آخر برای پاک کردن (برابر صفر قرار دادن) مقادیر ذخیره شده در حافظه EEPROM میتوانید از کد زیر استفاده کنید.
/* EEPROM Clear Sets all of the bytes of the EEPROM to 0. This example code is in the public domain. */ #include <EEPROM.h> void setup() { EEPROM.begin(512); // write a 0 to all 512 bytes of the EEPROM for (int i = 0; i < 512; i++) { EEPROM.write(i, 0); } // turn the LED on when we're done pinMode(13, OUTPUT); digitalWrite(13, HIGH); EEPROM.end(); } void loop() { }
لوازم مورد نیاز
این کتابخانه نیاز به ماژول خاصی ندارد. همانطور که گفته شد تمامی برد های آردوینو مبتنی بر تراشه های AVR از این کتابخانه پشتیبانی میکنند. برای تهیه بردهای آردوینو میتوانید از طریق لینک زیر اقدام کنید.
جمع بندی
در این آموزش ابتدا با تاریخچه و عملکرد حافظه EEPROM آشنا شدیم. همچنین فهمیدیم که حافظه EEPROM دارای عمر مفید است و قابلیت نوشتن بر روی آن محدود است. سپس میزان حافظه EEPROM در برد های مختلف آردوینو مورد بررسی قرار گرفت. در ادامه کتابخانه EEPROM.h و توابع کلیدی آن معرفی شد. در آخر سه نمونه کد برای نوشتن ، خواندن و پاک کردن حافظه EEPROM قرار داده شده است.
چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریعترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند میتوانید از همین طریق اطلاع رسانی کنید.
در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی , از وبسایت دیجی اسپارک حمایت کنید.
سلام
برای حافظه خارجی مثلا paralel eprom هم امکانش هست توضیح بدین
با سلام
ارتباط این نوع حافظه های EEPROM با توجه به تراشه ای که از آن استفاده میکنید، مشخص میشود. عموم این حافظه ها با رابط I2C به میکروکنترلر متصل میشود. کتابخانه ها مختلفی برای این نوع حافظه توسعه داده شده است که میتوانید از آن استفاده کنید.
سلام خسته نباشید
آیا فقط حافظه EEROM عمر محدود داره یا
حافظه فلش و sram هم عمری محدود داره اگر اینطور هست عمر هر کدوم چقدر هست با تشکر
با سلام
بله فقط حافظه های EEPROM هستند که عمر محدود دارند.
با سلام
می خواستم بدونم آیا می تونم به کد های این کتابخانه دسترسی پیدا کنم ؟
و آیا می تونم این کدها رو تغییر بدم؟
و آیا با اضافه کردن این کتابخانه به کدویژن می تونم از دستورات این کتابخانه در کدویژن استفاده کنم؟
با سلام
بله در صورتی که وارد پوشه فایل نصب شده آردوینو در سیستم خود شوید به کد های این کتابخانه دسترسی خواهید داشت. اما امکان استفاده از این کتابخانه در کدویژن نیست. در کدویژن کتابخانه EEPROM.h نیز وجود دارد اما توابع آن کمی با این کتابخانه متفاوت است.
سلام.
برای پیاده سازی این کدها روی برد wemos d1 چه مواردی باید تغییر کنه؟
با سلام
بایستی کتاخانه موجود برای میکروکنترلر های ESP8266 را بررسی کنید. ممکن است توابع موجود در این کتابخانه بر روی ESP کار نکند.
در یک پروژه ی ساعت ، اگر نخواهیم از باطری پشتیبان استفاده کنیم آیا میشه از این حافظه استفاده کرد؟ اگر بله ، پس عملیات محاسبه زمان در زمان قطعی برق چطور در میکروکنترلر انجام میشه
با سلام
استفاده از این حافظه راه درستی برای نگهداری ساعت نیست. راه دیگر برای داشتن ساعت دقیق، دریافت زمان از سرور های اینترنتی است. که میتوان در ابتدای برنامه پس از روشن شدن میکرو ساعت را از سرور دریافت کرده و داخل برنامه از آن استفاده کنید.
ایپرامهای سری ۲۴Cxx که با رابط ای تو سی وصل میشن هم دستورات خواندن نوشتنش همینه ؟ یا متفاوته -البته کتابخونش نصب بشه
با سلام
خیر این کتابخانه مروبط به حافظه EEPROM داخلی میکروکنترلر های موجود بر روی برد آردوینو هست. برای استفاده از EEPROM خارجی بایستی کتابخانه مروبطه را نصب و استفاده کنید.
با درود
اگر بخواهیم eeprom را پاک کنیم باید چکار کنیم؟دستوری برای این کار وجود دارد یا نه.به نظرم باید چند خط کد بنویسیم.
با سلام
در این آموزش ۳ مثال قرار داده شده است. مثال سوم نحوه پاک کردن حافظه EEPROM است.
سلام من یک اسکچ دارم که در ان از کتابخانه EEPROMex استفاده شده من میخاهم کتابخانه EEPROM را جایگزین این کتابخانه کنم ولی مشکی که هست به جای دستور EEPROM.readFloat وEEPROM.readByte و EEPROM.writeByte از چه دستوری استفاده باید کرد ؟
و اساسا تفاوت دستور EEPROM.readFloat با EEPROM.readByte در چیست ؟چون در جایی از دستورEEPROM.readFloat استفاده شده و در جایی دیگر EEPROM.readByte
با تشکر
با سلام
دستور EEPROM.readFloat و EEPROM.readByte در واقع برای خواندن اطلاعات از حافظه EEPROM به کار میروند و اختلاف اصلی آنها در نوع دادههایی است که از EEPROM خوانده میشوند.
۱- EEPROM.readFloat:
این دستور برای خواندن یک مقدار از نوع float (اعداد اعشاری) از حافظه EEPROM استفاده میشود.
EEPROM.readFloat یک عدد اعشاری ۴ بایتی را از EEPROM خوانده و به عنوان یک مقدار float باز میگرداند.
۲- EEPROM.readByte:
این دستور برای خواندن یک بایت از حافظه EEPROM استفاده میشود.
EEPROM.readByte یک عدد صحیح ۸ بیتی را از EEPROM خوانده و به عنوان یک مقدار byte (یک بایت) باز میگرداند.
بنابراین، اگر در کدی از EEPROM.readFloat استفاده شده باشد، این به معنای آن است که دادهای از EEPROM خوانده شده و به عنوان یک عدد اعشاری استفاده شده است. اگر از EEPROM.readByte استفاده شده باشد، داده به عنوان یک بایت صحیح خوانده شده و معمولاً برای ذخیره اطلاعات کوچکتر مانند شاخص یا وضعیت یک وضعیت (on/off) به کار میرود.
شاد و پیروز باشید.
سلام
ببخشید در سایت های دیگر که دیدم از حافظه EEPROM استفاده می کنند، از دستورEEP_Write_Stringبرای رایت کردن استفاده می کنند.من می توانم از کدام دستور استفاده کنم؟
با سلام
به مستندات کتابخانه مراجعه کنید. براساس متدی که شما کدنویسی میکنید میتوانید به روشهای مختلف اقدام کنید.