پیشرفته⏱ 16 دقیقه مطالعه

تا اینجا در تمام برنامه‌ها از loop() برای بررسی مداوم وضعیت پایه‌ها استفاده کرده‌ایم (به این روش Polling می‌گویند). اما این روش برای رویدادهای سریع یا نامنظم بهینه نیست. راه‌حل بهتر، استفاده از وقفه‌ها (Interrupts) است: تابعی که فقط دقیقاً در لحظهٔ وقوع یک رویداد (مثل فشردن دکمه) اجرا می‌شود.

ثبت یک وقفهٔ سخت‌افزاری

CPP
const int LED_PIN = 2;
const int BUTTON_PIN = 4;
volatile bool ledState = false;

void IRAM_ATTR onButtonPress() {
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), onButtonPress, FALLING);
}

void loop() {
  Serial.println("برنامه اصلی همچنان در حال اجراست...");
  delay(1000);
}
⚠️ هشدار

تابع وقفه (ISR) باید بسیار کوتاه و سریع باشد و حتماً با عبارت IRAM_ATTR‎ علامت‌گذاری شود (تا از حافظهٔ RAM سریع‌تر اجرا شود، نه فلش). از عملیات سنگین مثل delay طولانی، Serial.print زیاد، یا شبکه درون آن خودداری کنید؛ متغیرهایی که هم در ISR و هم در loop() استفاده می‌شوند باید volatile تعریف شوند.

تایمرهای نرم‌افزاری با کتابخانهٔ Ticker

کتابخانهٔ استاندارد Ticker (بخشی از هستهٔ ESP32-Arduino) به شما اجازه می‌دهد یک تابع را در بازه‌های زمانی مشخص، بدون مسدود کردن برنامهٔ اصلی، اجرا کنید — معادل کلاس Timer در میکروپایتون.

CPP
#include <Ticker.h>

const int LED_PIN = 2;
Ticker blinker;
bool ledState = false;

void toggleLed() {
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState);
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  blinker.attach(0.5, toggleLed);   // هر ۰٫۵ ثانیه صدا زده می‌شود
}

void loop() {
  // برنامهٔ اصلی آزاد است کارهای دیگری انجام دهد
}
شبیه‌سازی زندهٔ وقفهٔ دکمه — دقیقاً همین کد (attachInterrupt روی BUTTON_PIN=4 و LED_PIN=2) باز کردن در Wokwi ↗
در حال بارگذاری شبیه‌ساز… (ممکن است چند ثانیه طول بکشد)

این یک شبیه‌سازی واقعی و قابل اجراست؛ روی دکمه پخش (▶) در Wokwi بزنید تا کد روی برد مجازی ESP32 اجرا شود. اگر جعبهٔ بالا بیش از حد سیاه/خالی ماند، صفحه را رفرش کنید یا از دکمهٔ «باز کردن در Wokwi» بالا استفاده کنید.

🛠️ کارگاه عملی

کارگاه عملی: با استفاده از RISING به‌جای FALLING، رفتار متفاوت را مشاهده کنید و توضیح دهید چرا فرق می‌کند.

❓ چرا تابع ISR باید با IRAM_ATTR‎ علامت‌گذاری شود؟
طراحی و توسعه: امین شیخ نجدیglcd.ir | نسخهٔ افزونه: 1.21.0