آموزش مقدماتی AVR | جلسه هشتم

آموزش مقدماتی AVR | جلسه هشتم

آموزش میکروکنترلر AVR

با شما هستیم در قسمت هشتم آموزش میکروکنترلرهای AVR. در این قسمت، مبحث بسیار مهمی تحت عنوان وقفه یا اینتراپت را به شما همراهان I.G.E آموزش می‌دهیم. ابتدا مفهموم کلی وقفه را بیان میکنیم و سپس اولین مورد از وقفه‌ها یعنی وقفه خارجی را به طور کامل تشریح خواهیم کرد. همراه ما باشید.

اینتراپت یا وقفه چیست؟

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

آموزش مقدماتی AVR

حال دقیقا همین قضیه در میکروکنترلرهای AVR (یا حتی میکروکنترلرهایی نظیر PIC یا ARM) صادق است. فرض را بر این می‌گذاریم که قرار است عملیات شماره 1 بصورت مداوم اجرا شود و همچنین با زدن یک کلید عملیات شماره 2 انجام گردد. در این صورت شما نمی‌توانید بصورت مداوم CPU را در حال چک کردن پایه‌ای که کلید به آن متصل است رها کنید. چون باعث می‌شود عملیات شماره 1 به حالت توقف درآید. اینجاست که وقفه به کمک ما می‌آید.

روند اجرایی یک وقفه

با راه‌اندازی وقفه (حال هر وقفه‌ای که متناسب با کار ما باشد)، در حالت پیشفرض CPU در حال انجام عملیات شماره 1 است. ناگهان وقفه اتفاق می‌افتد. CPU عملیات شماره 1 را هرجایی که هست، رها کرده، عملیات شماره 2 را انجام داده و سرانجام به ادامه اجرای عملیات شماره 1 باز می‌گردد. تمام وقفه‌ها از این روند تبعیت می‌کنند.

آموزش مقدماتی AVR

شکل بالا به خوبی روند اجرایی یک وقفه توسط CPU را نشان می‌دهد.

بیت وقفه عمومی

در تمام میکروکنترلرهای AVR اگر بخواهیم از هرکدام از وقفه‌ها استفاده کنیم، اول باید بیت وقفه عمومی روشن شود. بیت وقفه عمومی الزام تمام وقفه‌هاست و در رجیستر SREG میکرو قرار دارد و با علامت I مشخص شده است.

آموزش مقدماتی AVR

بیت وقفه عمومی به دو صورت فعال می‌شود؛ اولین حالت فعال سازی بصورت زیر است.

SREG = SREG | 0x80;

چون بیت I بیت شماره 7 رجیستر SREG است، باید مقدار 0x80 را با خود آن OR کرد و داخل خودش ریخت ، راه دوم فعال سازی استفاده از دستور اسمبلی است.

#asm ("sei")

با استفاده از Asm# می‌توان یک خط اسمبلی میان کدهای C نوشت. دستور فوق بیت I را Set می‌نماید (یعنی 1 می‌کند).

انواع وقفه‌ها

در میکروهایی نظیر Mega8 یا Mega16/32 ما به طور کل 21 وقفه داریم که هرکدام مربوط به یک بخش هستند. شکل زیر تمام وقفه‌ها و دلیل وقوع آنها را شرح داده است.

آموزش مقدماتی AVR

در شکل بالا ستون Source نام وقفه‌های میکروکنترلر است و ستون Vector NO شماره وقفه است. این شماره از اهمیت بالایی برخوردار بوده و برای راه‌اندازی هرکدام از این وقفه‌ها، به این شماره احتیاج است.

سرویس روتین وقفه

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

interrupt[Vector شماره]void اسم دلخواه(void){
دستوراتی که با وقوع وقفه باید اجرا شوند
}

پس از نوشتن کلمه Interrupt، داخل براکت [ ] شماره Vector که شناسه منحصر به فرد وقفه است، نوشته می‌شود. با این کار معلوم می‌کنیم که این سرویس روتین مربوط به کدام وقفه است. کلمات کلیدی Void ثابت هستند و فقط یک اسم برای سرویس روتین نیاز است (اسم دلخواه). در ادامه به بررسی مفهوم وقفه خارجی خواهیم پرداخت؛ با توجه به اهمیت این بحث، خواهشمندیم که این قسمت را با دقت بخوانید!

وقفه خارجی

وقفه‌ خارجی به منظور تشخیص لبه یک سیگنال یا بصورت متداول‌تر برای خواندن کلیدها استفاده می‌شود. در تصویر قسمت بالا، وقفه‌های خارجی، INT1 ، INT0 و INT2 هستند و شماره Vector آنان به ترتیب 2 , 3 و 19 است. در شکل زیر پایه‌های مربوط به وقفه خارجی مشخص شده‌اند.

آموزش مقدماتی AVR

برای راه اندازی این وقفه‌ها 4 رجیستر در فضای SFR تعبیه شده است که عبارت‌اند از: MCUCR , GIFR , GICR و MCUCSR.
نکته: رجیسترهای نام برده دارای بیت‌های غیر مرتبط با وقفه خارجی نیز هستند که ما در این آموزش با آنها کاری نداریم.

رجیستر General Interrupt Control Register) GICR)

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

آموزش مقدماتی AVR

در انتهای این رجیستر سه بیت INT1 , INT0 و INT2 قرار دارند که با یک کردن هرکدام از آنها اینتراپت مربوط فعال می‌شود. البته باید دقت کرد که بیت اینتراپت عمومی که قبل تر راجب آن توضیح دادیم هم فعال باشد.

رجیستر General Interrupt Flag Register) GIFR)

هرگاه اینتراپت خارجی رخ دهد، بیت متناظر با آن اینتراپت یک شده و CPU از این طریق متوجه رخ دادن اینتراپت می‌شود.

آموزش مقدماتی AVR

همانطور که در شکل بالا می‌بینید، سه بیت INTF1 , INTF0 و INTF2 که به آنها بیت‌های Flag یا پرچم نیز گفته می‌شود، با رخ دادن اینتراپت 1 شده و CPU را مطلع می‌سازند. سپس CPU عملیات تعیین شده را انجام داده و در پایان به صورت اتوماتیک، همان بیت را 0 می‌کند.

رجیستر MCU Control Register) MCUCR)

این رجیستر نحوه چگونگی رخ دادن اینتراپت را معلوم می‌کند. مثلا اینتراپت با لبه بالارونده باشد یا لبه پایین رونده و … .

آموزش مقدماتی AVR

4 بیت کم ارزش این رجیستر متعلق به اینتراپت های خارجی 0 و 1 هستند. برای تنظیم این 4 بیت به شکل زیر توجه کنید.

آموزش مقدماتی AVR

دو بیت اول مربوط به وقفه شماره 0 و دو بیت دوم مربوط به وقفه شماره 1 است. هرکدام چهار حالت می‌توانند داشته باشند:

  1. اگر 00 مقداردهی شوند، سطح 0 منطقی باعث ایجاد وقفه می‌شود.
  2. اگر 01 مقداردهی شوند، هر دو لبه‌ی پایین رونده و بالارونده باعث ایجاد وقفه می‌شود.
  3. اگر 10 مقداردهی شوند، لبه پایین رونده وقفه ایجاد می‌کند.
  4. اگر 11 مقداردهی شوند، لبه بالا رونده وقفه ایجاد می‌کند.

رجیستر MCU Control and Status Register) MCUCSR)

همانند رجیستر MCUCR است. با این تفاوت که نحوه رخ دادن وقفه خارجی 2 را تنظیم می‌کند.

آموزش مقدماتی AVR

اینتراپت شماره 2 تنها یک بیت تنظیم به نام ISC2 دارد. اگر این بیت 0 شود، اینتراپت بصورت پایین رونده و اگر 1 شود اینتراپت بصورت بالارونده عمل می‌کند.

نکته: توصیه می‌شود رجیستر MCUCR و MCUCSR قبل از GICR و GIFR مقداردهی شود.

مثال اول

به عنوان اولین مثال میخواهیم برنامه‌ای بنویسیم که با فشردن یک کلید (لبه بالا رونده اینتراپت شماره 0)، Led های متصل به پورت A به ترتیب روشن و خاموش شوند و در انتها همه‌ی آنها خاموش گردد.

#include <mega16.h>
#include <delay.h>
unsigned char i;
void main(void){
DDRA = 0xFF;
PORTA = 0x00;
MCUCR = 0x03;
GICR = 0x40;
GIFR = 0x40;
#asm ("sei")
while(1);
}

    interrupt[2] void ext0(void){
        for(i=0;i<=7;i++){
        PORTA = 0x01 << i;
        delay_ms(300);
        }             
    PORTA = 0x00;
    }

از Main شروع می‌کنیم. پورت A را تماما خروجی کرده و مقدار آن را 0x00 میدهیم. سپس MCUCR را برابر 0x03 می‌کنیم. با اینکار مطابق جدول گفته شده، دو بیت ISC00 و ISC01 برابر 1 می‌شوند و وقفه در لبه بالا رونده رخ می‌دهد. حال باید خود وقفه فعال شود. با توجه به رجیستر GICR، باید بیت INT0 را یک کرد. پس مقدار 0x40 را اعمال میکنیم. همین مقدار را هم به GIFR می‌دهیم. در آخر هم بیت وقفه عمومی فعال شده و CPU وارد یک حلقه بدون دستور و بی پایان While می‌شود.

تا اینجای کار تنها وقفه فعال شد. در بیرون از Main با کلمه Interrupt که در بالا توضیح دادیم، سرویس روتین وقفه را می‌نویسیم. داخل براکت باید شماره Vector وقفه شماره 0 که عدد 2 است نوشته شود. نام دلخواه را هم Ext0 نوشتیم. حال به عنوان دستورات اجرایی با نوشتن حلقه For تمام Led های پورت A یکی یکی روشن می‌شوند. در آخر هم پورت A را صفر می‌کنیم.

آموزش مقدماتی AVR

نکته: چون اینتراپت در لبه بالا رونده تنظیم شده است، با یک مقاومت 10K پین INT0 را Pulldown کردیم تا در حالت عادی مقدار این پین 0 باشد.

مثال دوم

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

#include <mega16.h>
#include <delay.h>
unsigned char i;
bit direct;
void main(void){
DDRA = 0xFF;
PORTA = 0x00;
MCUCR = 0x03;
GICR = 0x40;
GIFR = 0x40;
#asm ("sei")

    while(1){
        for(i=0;i<=7;i++){
        PORTA = (direct)? (0x01 << i) : (0x80 >> i);
        delay_ms(300);
        } 
    }
}

    interrupt[2]void ext(void){
    direct = !direct;
    i = 7 - i;
    }

دستورات اولیه Main یکسان هستند. اما اینبار داخل While یک حلقه For نوشتیم که در هربار اجرا بسته به مقدار Direct یکی از مقادیر را به پورت A نسبت می‌دهد. اگر Direct یک باشد، مقدار (0x01 << I) به پورت ریخته می‌شود و اگر صفر باشد، مقدار (0x80 >> I) به پورت ریخته خواهد شد. در اولین حالت نمایش Led ها بصورت بالا رو و در دومین حالت بصورت پایین رو است.

اما برنامه سرویس روتین ساده است؛ کافی است تنها مقدار Direct را برعکس کنیم. همینطور باید مقدار I هم عوض شود تا هنگام تعویض جهت حرکت، پرشی دیده نشود (دلیل اینکار پیچیده است! خودتان آن را تحلیل کنید).

آموزش مقدماتی AVR

خب دوستان این بخش هم هرچند نسبت به دیگر بخش‌ها طولانی‌تر بود به اتمام رسید. مطمئنم هنوز سؤالات زیادی در مورد مبحث اینتراپت(و به خصوص اینتراپت خارجی) باقی مانده است؛ می‌توانید در آخر همین پست سؤالات و یا مشکلات خود را مطرح کرده تا تیم ما در کوتاه‌ترین زمان پاسخگوی شما عزیزان باشد.

برای آموزش‌ بعدی مبحث تایمر کانتر کلیک نمایید.

هیچ نظری وجود ندارد

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

شروع به تایپ کنید و Enter را برای جستجو وارد کنید

سبد خرید

هیچ محصولی در سبد خرید نیست.