25
آذر 1404
0 نظر

وقفه‌ها (Interrupts) در ESP8266 و ESP32 | آموزش جامع Interrupt در ESP

در این مقاله به‌صورت کامل با وقفه‌ها در ESP8266 و ESP32 آشنا می‌شوید؛ از مفاهیم پایه Interrupt و ISR تا پیاده‌سازی عملی، تایمرها، FreeRTOS و نکات حرفه‌ای

مقدمه: چرا Interrupt یکی از مهم‌ترین مفاهیم ESP است؟

در بسیاری از پروژه‌های ESP، مخصوصاً پروژه‌های IoT، صنعتی، سنسورمحور و Real-Time، واکنش سریع به رویدادها حیاتی است. اگر قرار باشد پردازنده دائماً داخل loop() منتظر بماند تا یک شرط برقرار شود، با مشکلات زیر روبه‌رو می‌شویم:

  • تأخیر در پاسخ

  • مصرف بیهوده CPU

  • از دست رفتن رویدادهای سریع

  • ناپایداری سیستم

اینجاست که وقفه‌ها (Interrupts) نقش کلیدی بازی می‌کنند.

Interrupt به ESP اجازه می‌دهد در لحظه وقوع یک رویداد مهم، اجرای برنامه را متوقف کرده و فوراً به آن پاسخ دهد. تسلط بر وقفه‌ها، مرز بین یک پروژه آماتور و یک پروژه حرفه‌ای را مشخص می‌کند.

 این مقاله مکمل مستقیم مباحث:


Interrupt چیست؟ (تعریف ساده و فنی)

وقفه یا Interrupt مکانیزمی سخت‌افزاری/نرم‌افزاری است که به پردازنده اعلام می‌کند یک رویداد مهم خارج از جریان عادی برنامه رخ داده است.

مراحل کار Interrupt:

  1. وقوع رویداد (مثلاً تغییر وضعیت GPIO)

  2. توقف موقت اجرای کد اصلی

  3. اجرای تابع وقفه (ISR)

  4. بازگشت به ادامه برنامه

این فرآیند معمولاً در چند میکروثانیه انجام می‌شود.


Polling در مقابل Interrupt

Polling چیست؟

در Polling پردازنده به‌صورت مداوم وضعیت یک ورودی را بررسی می‌کند:

if (digitalRead(buttonPin) == HIGH) { // action }

مشکلات Polling:

  • اشغال دائمی CPU

  • مصرف انرژی بالا

  • احتمال از دست رفتن پالس‌های سریع

مزایای Interrupt:

  • واکنش فوری

  • مصرف انرژی کمتر

  • مناسب پروژه‌های دقیق و Real-Time

به همین دلیل در سیستم‌های حرفه‌ای، Interrupt همیشه به Polling ترجیح داده می‌شود.


انواع وقفه‌ها در ESP

در ESP8266 و ESP32 چند نوع وقفه وجود دارد:

  1. وقفه خارجی (GPIO Interrupt)

  2. وقفه تایمر (Timer Interrupt)

  3. وقفه نرم‌افزاری

  4. وقفه‌های مرتبط با FreeRTOS (در ESP32)

در این مقاله هرکدام را به‌صورت کامل بررسی می‌کنیم.


وقفه خارجی (GPIO Interrupt)

رایج‌ترین نوع Interrupt، وقفه‌ای است که با تغییر وضعیت یک پایه GPIO فعال می‌شود.

حالت‌های فعال‌سازی (Trigger Mode)

  • RISING : تغییر از LOW به HIGH

  • FALLING : تغییر از HIGH به LOW

  • CHANGE : هر تغییری

  • HIGH / LOW : سطح ثابت (محدود)


پیاده‌سازی GPIO Interrupt در Arduino IDE

ساختار کلی استفاده از وقفه:

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

مثال ساده: وقفه کلید

const int buttonPin = 4; volatile bool buttonPressed = false; void IRAM_ATTR handleButton() { buttonPressed = true; } void setup() { pinMode(buttonPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(buttonPin), handleButton, FALLING); } void loop() { if (buttonPressed) { buttonPressed = false; // action } }

 در ESP32 استفاده از IRAM_ATTR ضروری است تا تابع ISR از RAM اجرا شود، نه از Flash.


ISR چیست و چرا باید سبک باشد؟

ISR یا Interrupt Service Routine تابعی است که هنگام وقوع وقفه اجرا می‌شود.

قوانین طلایی ISR

در ISR نباید:

  • از delay() استفاده شود

  • از Serial.print() استفاده شود

  • حافظه رزرو یا آزاد شود

  • عملیات سنگین انجام شود

ISR فقط باید:

  • فلگ ست کند

  • شمارنده افزایش دهد

  • زمان ثبت کند

نقض این قوانین یکی از دلایل اصلی ریست شدن ESP است.


volatile چیست و چرا حیاتی است؟

متغیرهایی که هم در ISR و هم در کد اصلی استفاده می‌شوند، باید با کلیدواژه volatile تعریف شوند.

volatile int counter = 0;

بدون volatile، کامپایلر ممکن است مقدار متغیر را به‌روزرسانی نکند و رفتار برنامه غیرقابل پیش‌بینی شود.

 این خطا در مقاله
«دیباگ و رفع خطاهای رایج در ESP»
به‌عنوان یکی از اشتباهات رایج بررسی شده است.


وقفه تایمر (Timer Interrupt)

Timer Interrupt وقفه‌ای است که در بازه‌های زمانی مشخص اجرا می‌شود.

کاربردها:

  • نمونه‌برداری دقیق سنسورها

  • تولید سیگنال

  • زمان‌بندی حرفه‌ای

  • کنترل موتور و PWM نرم‌افزاری

تایمرها در ESP32

ESP32 دارای تایمرهای سخت‌افزاری بسیار دقیق است که می‌توانند در سطح میکروثانیه وقفه ایجاد کنند.


تفاوت Interrupt در ESP8266 و ESP32

ویژگی ESP8266 ESP32
تعداد وقفه محدود زیاد
هسته پردازنده تک‌هسته دو هسته
FreeRTOS
Timer پیشرفته محدود کامل

ESP32 برای پروژه‌های حرفه‌ای انتخاب بهتری است.


Interrupt و FreeRTOS در ESP32

در ESP32، وقفه‌ها می‌توانند با Taskهای FreeRTOS تعامل داشته باشند.

ارتباط ISR با Task

  • ارسال سیگنال

  • استفاده از Queue

  • استفاده از Semaphore

 این مبحث به‌صورت کامل در مقاله
«اجرای چندین Task با FreeRTOS در ESP32»
بررسی می‌شود.


Debounce کلید در Interrupt

کلیدهای مکانیکی دارای پرش (Bounce) هستند.

راه‌حل نرم‌افزاری:

volatile unsigned long lastTime = 0; void IRAM_ATTR handleButton() { if (millis() - lastTime > 200) { lastTime = millis(); // valid press } }

انتخاب GPIO مناسب برای Interrupt

همه پایه‌ها برای وقفه مناسب نیستند.

❌ پایه‌های بوت
❌ پایه‌های متصل به Flash
❌ پایه‌های خاص ESP32-CAM

 لیست کامل این پایه‌ها در مقاله
«بوت‌لودر ESP و حالت‌های بوت»
بررسی شده است.


Interrupt و مصرف انرژی

Interrupt نقش مهمی در کاهش مصرف انرژی دارد:

  • CPU می‌تواند در حالت Idle یا Sleep بماند

  • فقط هنگام رویداد بیدار شود

این مفهوم پایه اصلی Deep Sleep است.

 مقاله مکمل:
«Deep Sleep و کاهش مصرف انرژی در ESP»


خطاهای رایج هنگام استفاده از Interrupt

❌ ریست شدن ESP

  • ISR سنگین

  • دسترسی به Flash در ISR

❌ اجرا نشدن وقفه

  • انتخاب GPIO اشتباه

  • تداخل با پایه‌های بوت


کاربردهای واقعی Interrupt در پروژه‌ها

  • شمارنده پالس و RPM

  • انکودر چرخشی

  • سنسور PIR

  • کلید اضطراری

  • دیتالاگر

  • سیستم هشدار

بیشتر پروژه‌های حرفه‌ای بدون Interrupt عملاً غیرممکن هستند.


جمع‌بندی نهایی

Interrupt یکی از پایه‌های اصلی برنامه‌نویسی حرفه‌ای ESP است.

اگر:

  • ISR را سبک بنویسی

  • از volatile درست استفاده کنی

  • GPIO مناسب انتخاب کنی

پروژه‌هایی خواهی داشت که:

  • سریع‌تر هستند

  • پایدارترند

  • کم‌مصرف‌ترند

  • و مقیاس‌پذیرند

این مقاله یکی از ستون‌های اصلی مرجع ESP تو خواهد بود.

ارسال نظر
(بعد از تائید مدیر منتشر خواهد شد)
  • - نشانی ایمیل شما منتشر نخواهد شد.
  • - لطفا دیدگاهتان تا حد امکان مربوط به مطلب باشد.
  • - لطفا فارسی بنویسید.
  • - میخواهید عکس خودتان کنار نظرتان باشد؟ به gravatar.com بروید و عکستان را اضافه کنید.
  • - نظرات شما بعد از تایید مدیریت منتشر خواهد شد