آموزش آردوینو

آموزش وقفه آردوینو بخش دوم

آموزش وقفه آردوینو Arduino
نوشته شده توسط علیرضا قربانی

در قسمت قبلی از آموزش وقفه ها در میکروکنترلر‌ها به شرح دقیق عمل‌کرد interrupt پرداختیم.اکنون در این قسمت قصد داریم به آموزش وقفه خارجی در پلت فرم آردوینو بپردازیم ، در ادامه با مرجع تخصصی آردوینو ، دیجی اسپارک همراه باشید.

در صورتی که بخش اول آموزش وقفه را مطالعه ننموده‌اید ، به شما پیشنهاد می‌کنیم قبل از مطالعه این پست ، بخش اول آموزش را در لینک زیر مشاهده کنید.

آموزش وقفه interrupt بخش اول

 

در قلب هر پردازنده‌ی آردوینو دو نوع وقفه داخلی و خارجی وجود دارد. تعداد وقفه‌های خارجی  در مدل های مختلف آردوینو متفاوت است و تعداد و پین‌های آن به صورت می‌باشد. پین‌های وقفه خارجی با پیشوند INT در آردوینو شناخته می‌شوند.

 

 

پین‌هایی که می‌توان از آن‌ها به عنوان پین وقفه استفاده نمود مدل آردوینو
۲, ۳ Uno, Nano, Mini, other 328-based
۲, ۳, ۱۸, ۱۹, ۲۰, ۲۱ Mega, Mega2560, MegaADK
۰, ۱, ۲, ۳, ۷ Micro, Leonardo, other 32u4-based
تمام پین‌های دیجیتال به جز پین شماره ۴ Zero
تمام پین‌های دیجیتال Due

 

 

توضیح توابع

 

attachInterrupt(interrupt, ISR, mode);

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

interrupt : شماری‌ وقفه ‌ایست که می‌خواهیم از آن استفاده کنیم.

تذکر:به‌جای آرگمان interrupt باید شماره وقفه را وارد نمود ، نه شماره‌ی پینی که می‌خواهیم از آن به عنوان وقفه خارجی از آن استفاده کنیم.

شماره وقفه‌ها در آردوینو به صورت زیر می‌باشد:

 

مدل آردوینو int.0

(وقفه شماره ۰)

int.1

(وقفه شماره ۱ )

int.2

(وقفه شماره ۲ )

int.3

(وقفه شماره ۳)

int.4

(وقفه شماره ۴)

int.5

(وقفه شماره ۵)

Uno, Ethernet ۲ ۳
Mega2560 ۲ ۳ ۲۱ ۲۰ ۱۹ ۱۸
۳۲u4 based (e.g Leonardo, Micro) ۳ ۲ ۰ ۱ ۷
Due, Zero (see below)

 

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

آردوینو Zero نیز همانند آردوینو Due می‌باشد با این تفاوت که از پین شماره ۴ آن نمی‌توان به عنوان وقفه خارجی استفاده نمود.

برای دو آردوینو Due و Zero می‌توان مستقیما از شماره پین به جای آرگمان interrupt در هنگام استفاده از تابع attachInterrupt استفاده نمود.

 

ISR : نام تابع وقفه‌ می‌باشد که به صورت اختیاری انتخاب می‌شود ، و پس از تحریک شدن پین وقفه‌ی مربوطه ، کدهای درون این تابع اجرا می‌شود. این تابع دارای خروجی نمی‌باشد ( از نوع void می‌باشد ) و نمی‌تواند آرگمان ورودی داشته باشد.

نکاتی پیرامون تابع وقفه :

  • تابع millis برای شمردن متکی به وقفه ها می‌باشد و مقدار آن هیچوقت درون تابع وقفه (ISR) افزایش پیدا نمی‌کند.
  • تابع delay برای کار کردن نیاز به وقفه‌ها دارد از این رو دستور delay هیچگاه درون تابع وقفه (ISR) اجرا نمی‌شود.
  • تابع micros در ابتدای کار ، درون تابع وقفه (ISR) به درستی عمل می‌کند ولی بعد از گذشت ۱-۲ میلی‌ثانیه به طور نامنظم کار می‌کند.
  • تابع delayMicroseconds برای افزایش مقدار خود به هیچ‌شمارنده‌ای وابسته نمی‌باشد بنابراین دستورdelayMicroseconds درون تابع وقفه (ISR) به درستی عمل می‌کند.
  • توجه کنید هیچگاه در تابع وقفه (ISR) پردازش‌های سنگین قرار داده نشود.
  • هیچ گاه دو تابع وقفه همزمان اجرا نمی‌شوند و به ترتیب اولویت موجود در جدول بردار وقفه اجرا می‌شوند.
  • هنگامی که یک متغیر را به طور سراسری تعریف می‌کنید و تمایل دارید مقدار متغیر درون تابع وقفه نیز بتواند تغییر کند باید قبل از تعریف متغیر از کلمه کلیدی volatile استفاده شود. با انجام این کار به کامپایلر یادآوری می‌کنیم که مقدار متغیر را در حافظه RAM و نه در یک رجیستر ذخیره کند و مقدار این متغیر می تواند خارج از برنامه (زیربرنامه وقفه یا سایر زیربرنامه ها) تغییر نماید.

 

 

 

mode : توسط این آرگمان نوع تحریک شدن وقفه مشخص می‌شود.دارای چهار حالت زیر می‌باشد :

  • LOW : هرگاه وضعیت پین interrupt در حالت LOW ( صفر منطقی) قرار داشته باشد ، تابع وقفه اجرا می‌شود.
آموزش interrupt آردوینو

LOW Mode

 

  • HIGH : هر گاه وضعیت پین interrupt  در حالت HIGH ( یک منطقی ) قرار داشته باشد ، تابع وقفه اجرا می‌شود. درست عکس حالت فوق.

 

  • CHANGE : هر گاه وضعیت پین INTERRUPT  از حالت صفر منطقی به  یک منطقی تغییر کند یا هرگاه از حالت ۱ منطقی به صفر منطقی تغییر کند، تابع وقفه اجرا می‌شود.

 

آموزش interrupt آردویتو

CHANGE Mode

 

RISING : هنگامی که وضعیت پین INTERRUPT از صفر منطقی به یک منطقی تغییر کند تابع وقفه اجرا می‌شود.

آموزش interrupt آردویتو

CHANGE Mode

 

آموزش interrupt آردویتو

RISING Mode

 

 

FALLING : هنگامی وضعیت پین INTERRUPT از یک مطقی به صفر منطقی تغییر کند ، تابع وقفه اجرا می‌شود.

FALLING Mode

آموزش intrrupt arduino

 

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

این تابع همانند تابع فوق می‌باشد با این تفاوت که در آرگمان اول از یک تابع دیگر به نام digitalPinToInterrupt استفاده شده است که به کمک آن می‌توانیم به جای شماره وقفه ، شماره‌ی پین وقفه را وارد کنیم به عنوان مثال برای استفاده از وقفه صفر طبق تابع قبلی باید مطابق کد زیر عمل می‌کردیم:

attachInterrupt(0, ISR, FALLING);

 

ولی با استفاده از تابع جدیدی که هم اکنون معرفی کردیم باید مطابق کد زیر عمل کنیم :

attachInterrupt( digitalPinToInterrupt(2) , ISR, FALLING);

 

detachInterrupt()

این تابع وقفه مورد نظر را غیرفعال می‌کند و آن پایه که وقفه به آن نسبت داده شده بود به ورودی / خروجی تغییر می‌دهد. این تابع دارای  ساختارهایی به صورت زیر می‌باشند.

detachInterrupt (interrupt);	   //شماره وقفه را وارد می کنیم

detachInterrupt (digitalPinToInterrupt (pin));	 //شماره پین وقفه را وارد میکنیم

detachInterrupt (pin);		  //می توان از این ساختار استفاده نمود Zero و  Due فقط در آردوینو

 

noInterrupts()

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

 

interrupts()

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

 

 

مثالی از وقفه در Arduino :

int ledPin = 13;  // LED is attached to digital pin 13
volatile  int x = 0;  // variable to be updated by the interrupt

void setup() {
  //enable interrupt 0 (pin 2) which is connected to a button
  //jump to the increment function on falling edge
  attachInterrupt(0, increment, FALLING);
  Serial.begin(9600);  //turn on serial communication
}

void loop() {
  digitalWrite(ledPin, LOW);
  delay(3000); //pretend to be doing something useful
  Serial.println(x, DEC); //print x to serial monitor
}

// Interrupt service routine for interrupt 0
void increment() {
    x++;
    digitalWrite(ledPin, HIGH);
}

 

درباره نویسنده

علیرضا قربانی

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

تبادل نظر و رفع عیب با ثبت دیدگاه

۱۴ دیدگاه

  • باسلام و تشکر بابت مطالب ارائه شده
    لطفا در مورد مد اسلیپ و ترکیب اون با وقفه خارجی هم آموزش بدید یا لینک معرفی کنید.
    باسپاس فراوان

    • void setup(){
      // put your setup code here, to run once:
      pinMode(0,INPUT_PULLUP);
      pinMode(1,INPUT_PULLUP);
      pinMode(2,INPUT_PULLUP);
      pinMode(3,INPUT_PULLUP);
      pinMode(4,INPUT_PULLUP);
      pinMode(5,INPUT_PULLUP);
      pinMode(6,INPUT_PULLUP);
      pinMode(7,INPUT_PULLUP);
      pinMode(8,OUTPUT);
      pinMode(9,OUTPUT);
      pinMode(10,OUTPUT);
      pinMode(11,OUTPUT);
      pinMode(12,OUTPUT);
      }
      void loop(){
      // put your main code here, to run repeatedly
      bool bac=digitalRead(0);
      bool AUTO=digitalRead(1);
      bool MANU=digitalRead(2);
      bool mic1= digitalRead(3);
      bool mic2= digitalRead(4);
      bool mic3= digitalRead(5);
      bool mic4= digitalRead(6);
      bool mic5= digitalRead(7);
      bool valv1=digitalRead(8);
      bool pump1 = digitalRead(9);
      bool pump2 =digitalRead(10);
      bool valv2= digitalRead(11);
      bool memory1=digitalRead(12);
      if(AUTO==LOW&mic1==LOW&mic2==LOW&mic3==LOW||MANU==LOW){
      digitalWrite(12,HIGH);
      digitalWrite(8,HIGH);
      delay(4000);
      digitalWrite(9,HIGH);
      }
      else
      {
      digitalWrite(12,LOW);
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);
      }
      if(mic5==LOW&memory1==HIGH){
      delay(5000);
      digitalWrite(10,HIGH);
      digitalWrite(11,HIGH);
      delay(1000);
      digitalWrite(11,LOW);@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      }
      if(bac==LOW)
      {digitalWrite(8,HIGH);
      digitalWrite(9,HIGH);
      }
      }
      سوالی در مورد این پروژه که نوشتم داشتم چه طور میتونم مطرح کنم

      • با سلام
        کاربر گرامی ضمن تشکر از شما، امکان بررسی کدهای متفرقه در بخش کامنت ها فراهم نیست. موضوع سوال خود را مطرح کنید تا به لینک های مناسب هدایت شوید.

  • سلام
    چرا انقدر این وقفه محدودیت داره !!!
    تابع pulsein رو تو ISR اجرا نمیکنه باید چیکار کنم؟ راه دیگه نداره؟

  • من در کل نظر نمیدم ولی این مطالب انقدر مفید و عالی توضیح داده شده بودن که حیفم اومد نظرمو نگم
    امیدوارم همشیه موفق باشی

  • ممنون بابت مطالب مفیدی که ارائه دادید. در یک پروژه به وسیله آردوینوuno از هردو وقفه خارجی استفاده می کنم. یکی از وقفه ها به یک انکودر ۴۰۰ پالس متصل هست و دومی به یک سنسور مغناطیس جهت شمارش. به نظرم وقفه متصل به انکودر فرصتی به وقفه دو نمیده که بتونه اجرا بشه! این مشکل رو چطور رفع کنم؟

  • با سلام به دست اندرکاران دیجی اسپارک
    در برنامه ای که بنده نوشتم تابع وقفه اجرا میشه اما شروط موجود در ان به هیچ وجه اجرا نمی شوند به نظر شما مشکل از کجا میتواند باشد
    کانفیک وقفه
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(2), Interrupt, LOW);
    digitalWrite ( ledPin1 , HIGH ) ;
    //————-
    void Interrupt() {
    delayMicroseconds(20);
    Serial.println(“Interrupt”);
    if (Key == LOW) { // این قسمت کار نمیکند
    if (m == 1) {
    m = 2 ;
    Serial.print(“mode = 2”);
    digitalWrite ( ledPin1 , HIGH ) ;
    digitalWrite ( ledPin2 , LOW ) ;

    }
    if (m == 2) {
    mode = 1 ;
    Serial.print(“mode = 1”);
    digitalWrite ( ledPin1 , LOW ) ;
    digitalWrite ( ledPin2 , HIGH ) ;
    }
    }
    }

  • سلام
    من با ارنج پای one و نرم افزار node-red میخوام با فعال سازی اینتراپت یک ورودی رو بخونم ؛ تو خوده تنظیمات پین فعال سازی اینتراپت رو انجام می دم ولی وقتی ورودی رو فعال می کنم هیچ اتفاقی نمی افتد و با دیباگ هم چک کردم پین هیچ خروجی نداره برای فعال سازی وقفه روی پین PA6 تنظیم دیگر رو هم باید انجام بدم ؟