به نام خدا : آموزش جامع میکروکنترلر AVR جلسه۳ – انشا الله قراره تو این جلسه در مورد وقفه یه سری توضیح بدم + یه پروژه هم در ته همین مطلب گزاشتم با وقفه نوشته شده است.
آموزش جامع میکروکنترلر AVR جلسه۳
انشا الله قراره تو این جلسه در مورد وقفه یه سری توضیح بدم + یه پروژه هم در ته همین مطلب گزاشتم با وقفه نوشته شده است.
وقفه در AVR
توجه مهم : وقفه به معنی تاخیر زمانی نیست!
بزارید با یه مثال توضیح بدم ، مثال : ما میخایم یه LED رو با یه کلید روشن و خاموش کنیم ؟ دو تا راه داریم :
۱) روش سرکشی (Polling)
ما تو تابع MAIN میایم و میگیم هر موقع که ما کلید رو زدیم فلان پایه ی میکرو فعال شد (یا همون ۱منطقی شد) ، اون وقت جنابعالی (منظور میکروکنترلر هستش) هم فلان پایه میکرو رو فعال کن تا LED روشن بشه. حالا مشکل زمانی هستش که ما هنوز کلید رو نزدیم و جناب میکروکنترلر مجبوره که هی بره و ببینه که آیا فلان پایه فعال شده یا نه و هی میره و هی برمیگرده (بیچاره خسته نمیشه این همه راه رو میره !!! ) البته تا حالا من خودم از همین روش استفاده کردم !!! و از روش زیر استفاده نکردم.(آخه چه کاریه گره ای که با دندون باز میشه چرا با دست بازش کنی !!!)
۲) روش وقفه ( Interrupt )
تو این روش برخلاف روش قبلی به جای این که ما هی بریم و برگردیم تا بفهمیم که آیا فلان پایه فعال شده یا نه میاییم یه کاری میکنیم : یه موبایل برا دو طرف میخریم و هر موقع که اون پایه هه فعال شد زنگ میزنه به میکرو و میگه دادا بدو بیا که فعال شدم !!! لپ کلوم ای که تو این روش اگه پایه فعال شد خودش ما رو خبر میکنه و دیگه لازم نیس که هی بریم و هی برگردیم و بررسی کنیم که ۱ شده یا نه … حالا چطور میاد ما رو خبر میکنه رو در ادامه مطلب میگم …
انواع وقفه
۱) وقفه داخلی : تقریبا تمام امکانات داخلی میکرو دارای وقفه بوده مانند تایمر – کانترها و پروتکل های ارتباطی و مقایسه کننده ها و مبدل آنالوگ به دیجیتال. ( این مورد زیاد کاری نداریم فعلا، مورد بعدی هستش که میخوام تو این مطلب آموزش بدم.)
۲) وقفه خارجی : در میکرو پایه هایی به نام INTx وجود دارد که زمانی تحریک شوند ، میکرو به زیر برنامه وقفه پرش می کند و کار تعیین شده را انجام می دهد.این وقفه ها می توانند با یک لبه بالا رونده یا پایین رونده و یا یک منطقی تحریک شوند.
نکته : هنگامی که یک پایه به عنوان وقفه استفاده شود دیگر نمی توانیم از آن پایه به عنوان ورودی یا خروجی استفاده کنیم. این یه میکرو کنترلر avr از نوع atmega16 هستش که توش پایه های وقفه صفر-وقفه۱ و وقفه ۲ رو مشخص کردم.
توضیح رجیسترهای وقفه
۱) ریجستر SREG
بیت ۷ ( I ) : با یک کردن این بیت ، وقفه سراسری یا کلی فعال میشود.(یعنی میتونیم از وقفه استفاده کنیم.)
توجه مهم : اگه بخواید از وقفه استفاده کنید این بیت حتما باید یک بشه.که این بیت به صورت زیر فعال/غیر فعال میشود.
1 2 |
#asm("sei") //فعال کردن وقفه سراسری #asm("cli") //غیر فعال کردن وقفه سراسری |
۲) ریجستر GICR
تو این ریجستر ما فقط با ۳ بیت آخرش کار داریم.
بیت ۷ (INT1 ) : با یک کردن این بیت و استفاده از دستور (“asm(“sei#وقفه۱فعال میشود. متناظر با پایه PORTD.3 میباشد.(اون عکس میکروکنترلر avr که در بالا هستش رو نگاه کنید)
بیت ۶ (INT0 ) : با یک کردن این بیت و استفاده از دستور (“asm(“sei# وقفه ۰ فعال میشود. متناظر با پایه PORTD.2 میباشد.(اون عکس میکروکنترلر avr که در بالا هستش رو نگاه کنید)
بیت ۵ (INT2 ) : با یک کردن این بیت و استفاده از دستور (“asm(“sei# وقفه ۲ فعال میشود. متناظر با پایه PORTB.2 میباشد.(اون عکس میکروکنترلر avr که در بالا هستش رو نگاه کنید)
۳) ریجستر GIFR
جواب۱ : تو بعضی ریجسترها ممکنه یک یا چند بیت وجود داشته باشه که بهش میگن پرچم.
سوال۲ : حالا این پرچم ها کارشون چیه؟
جواب۲ : همون طور که میدونید یه بیت دو حالت میتونه داشته باشه، یا ۰ هستش و یا ۱، حالا این یه بیت(که بهش میگن پرچم) مثلا تو همین بحث وقفه خارجی، و همین ریجستر GIFR که ۳بیت آخرش پرچم هستش، برا هر وقفه خارجی یه پرچم داریم، حالا من پرچم مربوط به وقفه ۰(که میشه بیت ۶ام) رو توضیح میدم : اگه وقفه خارجی۰ رخ بده این بیت(یا این پرچم) مقدارش ۱میشه، مثلا در مواقعی که نخوایم از تابع وقفه استفاده کنیم، میتونیم از این پرچم در برنامه مون در تابع main برا تشخیص رخ دادن و یا عدم رخ دادن وقفه ازش استفاده کنیم.
در صورت فعال کردن بیت های ریجستر GICR، پرچم های متناظر با اون وقفه در این ریچستر به صورت خودکار مقدارشون پاک میشه، ولی اگه اون بیت های ریجستر GICR رو فعال نکرده باشید، باید خودتون با دادن مقدار ۱ به پرچم مربوطه در این ریجستر، مقدارشون رو پاک کنید!(پرچم ها با دادن ۱ بهشون مقدارشون پاک میشه!!!)
۴) ریجستر MCUCR
این ریجستر هم ریجستر مهمی هستش O_o
ما با نحوه مقدار دهی این ریجستر (که در ادامه میگم) میتونیم نحوه فعال و غیر فعال شدن (نحوه تحریک شدن) وقفه رو تعیین کنیم.
(اگه تو کد ویژن تو قسمت کد ویزاردش و تو قسمت! تعیین وقفه ها و تو قسمت MODE رو نگاه کرده باشید، وقفه صفر و یک ۴ تا حالت داره اما وقفه ۲ ، فقط دو حالت داره.)
جدول زیر که انواع مقدار دهی بیت های ISC01 و ISC00 رو نشون داده که مربوط به وقفه صفر هستش.
۱) ۰=ISC01 و ۰=ISC00 : سطح منطقی۰ (۰ولت) باعث رخ دادن وقفه۰ میشه.
۲) ۰=ISC01 و ۱=ISC00 : هر نوع تغییری باعث رخ ددن وقفه۰ میشه.
۳) ۱=ISC01 و ۰=ISC00 : اگه از حالت ۱منطقی(۵ولت) به ۰منطقی(۰ولت) بریم وقفه۰ رخ میده.
۴) ۱=ISC01 و ۱=ISC00 : اگه از حالت ۰منطقی(۰ولت) به ۱منطقی(۵ولت) بریم وقفه۰ رخ میده.

جدول زیر هم مربوط به وقفه یک هستش.
که دیگه من توضیح نمیدم ، چون مثل حالت بالا هستش.

۵) ریجستر MCUCSR
با توجه به توضیحاتی که در بالا دادم ، نحوه تحریک این وقفه که وقفه ۲ هست بر خلاف وقفه ۱ و ۰ که ۴ تا حالت داشت ولی وقفه ۲ فقط دو حالت دارد لذا دیگر از جدول مدول خبری نیست.
۱) ۰=ISC2 : اگه از حالت ۱منطقی(۵ولت) به ۰منطقی(۰ولت) بریم وقفه۲ رخ میده.
۲) ۱=ISC2 : اگه از حالت ۰منطقی(۰ولت) به ۱منطقی(۵ولت) بریم وقفه۲ رخ میده.
فعال کردن وقفه در کدویژن
تو کد ویژن وقتی یه پروژه جدید ایجاد میکنی و میری تو قسمت کد ویزارد ، میتونی وقفه رو از همون جا فعال کنی و دیگه کد مد ننویسی.
تو قسمت mode 4 تا حالت داریم که در بالا توضیح دادمش.
سه تا وقفه رو فعال کردم و حالت MODE هر سه رو گزاشتم رو گزینه آخر و بعد …
توجه : البته کدهایی که برنامه تولید کرد خیلی بیشتر از این بود که من کد های اضافه و غیر مربوط به این موضوع (وقفه) رو حذف کردم تا مرتب تر بشه.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <mega16.h> interrupt [EXT_INT0] void ext_int0_isr(void){ } interrupt [EXT_INT1] void ext_int1_isr(void){ } interrupt [EXT_INT2] void ext_int2_isr(void){ } void main(void) { GICR|=0xE0; MCUCR=0x0F; MCUCSR=0x40; GIFR=0xE0; #asm("sei") while (1){ }; } |
آموزش کد نویسی تابع وقفه
1 2 3 4 |
interrupt [EXT_INT0] نام تابع(void) { محل قرار گیری کد های شما } |
البته به جای EXT_INT0 میتونستیم عدد ۲ رو قرار بدیم .
و به جای EXT_INT1 میتونستیم عدد ۳ رو قرار بدیم .
و به جای EXT_INT2 میتونستیم عدد ۱۹ رو قرار بدیم .


پروژه های وقفه avr
پروژه avr یک
این هم یه پروژه ساده هستش که اگه رو کلید کلیک کنی LED روشن و دوباره اگه کلیک کنی خاموش میشه و ….
که با وقفه صفر نوشته شده است.
پروژه avr دو
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <mega16.h> #include <stdlib.h> #include <delay.h> #asm .equ __lcd_port=0x1B ;PORTA #endasm #include <lcd.h> interrupt [EXT_INT0] void ext_int0_isr(void) { PORTB.0=!PORTB.0; } void main(void) { int i=0; char str[10]; DDRB=0XFF;; // External Interrupt(s) initialization // INT0: On // INT0 Mode: Rising Edge // INT1: Off // INT2: Off GICR|=0x40; MCUCR=0x03; MCUCSR=0x00; GIFR=0x40; #asm("sei")// Global enable interrupts lcd_init(16); while (1) { for(i=0;i<=999;i++) { itoa(i,str); lcd_gotoxy(0,0);lcd_puts(str);lcd_puts(" "); delay_ms(100); } }; } |


سوالی بود در خدمتیم اگه هم نبود یا علی.
کتابخانه راه اندازی وقفه خارجی میکرو کنترلر avr
1 2 3 4 5 6 7 8 |
void Interrupt0Init( unsigned char InterruptSense ) void Interrupt1Init( unsigned char InterruptSense ); void Interrupt0Enable(); void Interrupt0Disable(); void Interrupt1Enable(); void Interrupt1Disable(); void Interrupt0ClearFlag(); void Interrupt1ClearFlag(); |
برا تعیین نوع تحریک شدن وقفه های خارجی میتونید از یکی از ثوابت زیر استفاده کنید :
1 2 3 4 5 |
// InterruptSense #define LOW 0 #define anyChange 1 #define FALLING 2 #define RISING 3 |
در تابع زیر روال وقفه ( همون تابع وقفه که در بالا آموزشش رو دادم ) برا تعیین این که این زیر روال برا کدوم وقفه خارجی هستش از یکی از دو ثابت زیر میتونیم استفاده کنیم :
1 2 |
#define EXT_INT0_vec ۲ #define EXT_INT1_vec ۳ |
مهمان
سلا م مهندس
من به برنامه در avr codevision نوشتم که برای تنظیم و بالا و پایین بردن عددی از وقفه 0و1و 2 استفاده کردم این برنامه با سیمولیشن خوب کار میکنه ولی با برد خوب کار نمی کنه میشه برای مشکل من یه راه حل ارایه بدی
مهمان
سلام و وقت بخیر
چرا تو کد پروژه اولی نوشتین MCUCR رو رایز تنظیم کردین ولی تو تابع وقفه نوشتین while(PORTD.2==1); ؟ مگه در این صورت معنیش این نیس که وقتی یک میشه ینی رایز رخ میده هیچ کاری نکن؟؟؟
مهمان
من یه چیزی فهمیدم اصلا لزومی به نوشتن while نیس چون که با تحریک بالارونده پایه مربوط به وقفه خودش میره نقیض رو انجام میده
مهمان
اشکال بعدی هم اینه که PIND.2 باید بنویسیم نه PORTD.2. اگه نوشتیم while رو میشه جوری کرد که با رها کردن کلید از طریق while تغییرات رخ بدن نه فشردنش
نویسنده این مطلب
این کدو من اصلا تو مطلب پیدا نکردم، نمیدونم به چه موضوعی شما دارید اشاره میکنید.
while(PORTD.2==1)
مهمان
پروژه اول همین مطلب
مهمان
سلام
دمت گرم
خیلی خیلی مردی
مهمان
سلام به غیر از پایه های int پایه های دیگه رو هم میشه اینتراپت کرد؟
نویسنده این مطلب
سلام / نه نمیشه، ولی برخی میکرو های سری مگا همچین قابلیت رو دارن، ولی خب اونا هم 2-3 تا وقفه اختصاصی دارن، بقیه پایه ها بین این 2-3 تا تقسیم میشن، یعنی مثلا 8 تا پایه میکرو از 1 وقفه به صورت مشترک استفاده میکنن و اگه هر کدوم از این پایه ها فعال بشه، وقفه فوق رخ میده که داخل اون وقفه باید بیای بررسی کنی که کدوم یک از این 8 تا پایه فعال شده.
مهمان
سلام خسته نباشبد
من یک سوال داشتم اینک
اگر تعداد وقفه ها ی تودر تو بیشتر از دو تا باشه و روی میکروکنترلر بیشتر از دوپایه برای وقفه باشه واکنش سیستم چیه
مهمان
بیاییم همه با هم بگوییم:
اللهم عجل لولیک الفرج
مهمان
سلام یه سوال خیلی مهم دارم
من میخوام برای اینکه برنامم خیلی سنگین نشه، از متغیر سراسری کمتری استفاده کنم. حالا سوال اینجاست که چطوری میشه یه داده رو از داخل اینتراپت به داخل تابع مین انتقال بدیم، آنهم بدون متغیر سراسری
آیا با نشانگر میشه اینکار رو انجام داد؟ یعنی میشه در داخل اینتراپت آدرس متغیر داخل مین رو داد و تغییر ایجاد کرد؟
آیا این کار یعنی دادن آدرس و پوینتر بهتره یا همون متغیر سراسری
از حیث سرعت میکرو و کم کردن بار میکرو میگم
آیا راه حل دیگه ای وجود دارد؟
خیلی خیلی ممنون
یا علی
نویسنده این مطلب
سلام / بنظرم از همون متغییر سراسری استفاده کن و خودتو درگیر این اشاره گرها و … نکن.
مهمان
سلام دوباره
یه سوال دیگه داشتم دوست عزیزم و استاد گرامی
آیا استفاده از حافظه اییپرام سرعت میکرو را پایین می آورد؟ آیا باعث هنگ کردن میکرو میشود؟ اصلا چه محاسن و معایبی دارد؟
ببینید من برای اینکه با خاموش و روشن شدن اطلاعت برنامم از دست نره مجبورم از اییپرام استفاده کنم. مثلا برای ماندگاری ساعت و تقویم
حالا آیا استفاده هر ثانیه از اییپرام برای ثبت ثانیه مشکلی ایجاد میکنه، آیا بهتره هر دقیقه یا ساعت این کار رو بکنم؟
آیا اییپرام عمر مفید دارد؟ یعنی با چند بار رید رایت خراب میشود؟
بسیار ممنونم استاد تکی
یا علی
نویسنده این مطلب
سلام / سرعت میکرو رو پایین بیاره؟ عمل ذخیره/خوندن هر چقدر طول بکشه، میکرو هم همونقدر علاف میشه ( چون تو میکرو داستان چن نخی ( اجرای موازی کدها ) وجود نداره ( غیر از داستان وقفه ها ) فلذا کدها بترتیب پشت سرهم اجرا میشه وبطبع بر اون قسمت ذخیره/خوندن ایپرام، میکرو الاف میشه )
بحث عمر مفید رو هم باید تو دیتاشیت میکرو بخونی که مقدارشو چند ذکر کرده.
مهمان
سلام
تو میکرو ATMEGA328 چه طور میشه از PCINT01 , PCINT02 همزمان استفاده کرد؟
مثلا دو تا دکمه داریم می خوایم هرکدوم یه کار خاص انجام بدن
چه طور باید کدش رو بنویسم؟
برای یه دونه فهمیدم اما دوتا با هم رو نفهمیدم؟؟؟