سلام دوستان. در قسمت قبلی آموزش میکروکنترلر STM32 بهمعرفی وقفه خارجی در میکروکنترلر STM32 پرداختیم. حالا که فراگرفتیم چطور وقفه خارجی را در میکروکنترلر STM32 تعریف کنیم، در این قسمت قصدداریم بررسیکنیم چطور چند وقفه خارجی در یک برنامه داشتهباشیم و چطور باید آنها از یکدیگر تفکیککنیم.
شروع تغییرات
به محیط CubeMX میرویم و تغییرات را مطابق عکسزیر اعمال میکنیم. سه خروجی مجزا و سه اینتراپت خارجی را برای میکروکنترلر STM32 تعریف میکنیم:
همانطورکه مشخصشده ما سه اینتراپت خارجی و سه خروجی مجزا انتخابکردیم. قرار است برنامه بدین صورت باشد که با فعالشدن هرکداماز اینتراپتهای خارجی، وضعیت خروجی متناظر با آن بالعکس شود. بدینمنظور با کلیک راست کردن روی هرکدام از پایههای اینتراپت خارجی لیبل مناسب آن را متناسب با هر خروجی تعیین میکنیم.
همانطورکه مشخصشده ما سه اینتراپت خارجی و سه خروجی مجزا انتخابکردیم. قرار است برنامه بدینصورت باشد که با فعالشدن هرکدام از اینتراپتهای خارجی، وضعیت خروجی متناظر با آن بالعکس شود. بدینمنظور با کلیک راست کردن روی هرکدام از پایههای اینتراپت خارجی لیبل مناسب آن را متناسب با هر خروجی تعیین میکنیم.
حالا تنظیمات را OK میکنیم و سپس دکمه NVIC را میزنیم و تنظیمات را مطابق عکسزیر اعمال میکنیم:
خوب همانطورکه در شکل میبینید، سه اینتراپت خارجی داشتیم ولیکن در اینجا دو گزینه برای فعالسازی اینتراپت خارجی وجود دارد. دلیلش هم این است که اینتراپت خارجی ۲ و ۳ چون شماره پینهایشان در محدوده ۱۰ تا ۱۵ است زیرمجموعه گزینه EXTI line[۱۵:۱۰] هستند و اینتراپت خارجی ۱ بدلیلاینکه شماره پینش در محدوده ۵ تا ۹ است زیرمجموعه گزینه EXTI line[۹:۵] میباشد. در ادامه توضیحات درمورد محدودههای مشخصشده برای اینتراپتهای خارجی بیشتر توضیحداده خواهدشد. فقط نکته بسیارمهمی که باید ذکرشود ایناست که شما نمیتوانید همزمان دو وقفه خارجی برای دو پین متناظر از دو پورت متفاوت را داشتهباشید. بهعنوانمثال اگر شما درحالی PB15 را قبلاً بهعنوان اینتراپت خارجی انتخاب کردهاید اگر درهمانحال اینبار PA15 را هم بهعنوان اینتراپت خارجی تنظیمکنید، مطابقشکلزیر خودبهخود اینتراپت خارجی PB15 منتفی میشود و تنظیم پایه PB15 به حالت پیشفرض برمیگردد.
بعداز طی مراحل تنظیمات را ok میکنیم و از CubeMX خروجی میگیریم و پروژه را با نرمافزار keil باز میکنیم. قبلاز اینکه به متن برنامه برویم بهتر است ابتدا به قسمت معرفی بردارهای وقفه برویم تا بیشتر با محدوده توابع وقفههای خارجی آشنا شویم.
همانطورکه در عکس بالا میبینید ما در برگه stm32f103xb.h و در قسمت معرفی وقفهها برای ۵بیت اول پورت، ۵روتین وقفه جداگانه داریم و برای بیت ۵تا ۹ یک وقفه مشترک و برای بیت ۱۰ تا۱۵ یک وقفه مشترک دیگر خواهیمداشت. حالکه این نکته را آموختیم بهتر است سراغ متن برنامه برویم. ابتدا به برگه stm32f1xx_it.c نگاهی میاندازیم:
*کادر بنفش: وقفه بیت ۵ پورت A*
*کادر قرمز: وقفه بیت ۱۲ و ۱۵ پورت B*
خوب همانطورکه مشاهده میکنید، ما در اینجا دو روتین وقفه داریم که اولی وقفه خارجی PA5 را پوشش میدهد و دومی وقفههای خارجی PB12 و PB15 را دربرمیگیرد. حال باید مثل برنامه قبل تابع HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) را داخل main برنامه قراردهیم و کدهای مربوطه را طبق عکسزیر جایگذاری کنیم:
خوب همانطورکه در برنامه مشخصاست هنگام رخدادن وقفه خارجی، ابتدا بررسی میشود که وقفه رخ داده مربوطبه کدام پین مشخص است. بعداز آن متناظر با وقفه رخ داده وضعیت یک خروجی بالعکس میشود. خوب تقریباً به پایان مبحث وقفه خارجی رسیدیم ولیکن ذکر چند نکته خارج از لطف نیست.
- یک اینکه ما چگونه میتوانیم در طول برنامه یک وقفه خارجی را فعال یا غیرفعال کنیم.
- دوم اینکه چطور اولویت یک وقفه را تغییردهیم.
- سوم اینکه چگونه میتوانیم نوع لبه تحریک یک وقفه را تغییردهیم.
درمورد سوال اول و دوم پاسخ بسیارساده است. بدینمنظور بهتر است به تابع MX_GPIO_Init(void) برویم تا شکل کار را متوجهشویم. حال به عکسزیر که از قسمتی از کدهای این تابع تهیهشده توجهکنید:
*کادر بنفش: تعیین اولویت وقفه*
*کادر قرمز: فعال کردن دو روتین وقفه خارجی مورداستفاده*
همانطورکه در شکل مشخص است ما میتوانیم ازطریق تابع HAL_NVIC_EnableIRQ وقفه موردنظرمان را فعالکنیم و برای غیرفعالکردن وقفه موردنظر هم میتوانیم از تابع HAL_NVIC_DisableIRQ که در برگه stm32f1xx_hal_cortex.c قرار دارد استفادهکنیم. شکل استفاده از این دو تابع هم مشابه یکدیگر میباشد، یعنی اینکه اسم تابع را مینویسیم و آرگومان آنرا همنام وقفه خود قرار میدهیم و برای تعیین اولویت وقفه هم از تابع HAL_NVIC_SetPriority که مطابق عکس زیر دو آرگومان دارد استفاده میکنیم. این تابع دو آرگومان دارد که آنها بستهبه اولویت وقفه میتوانند مقدار صفر تا ۱۵ را به خود اختصاص دهند. بااین توضیح که هرچه عدد کمتر باشد اولویت وقفه بالاتر است، توجهداشتهباشید در این برنامه بهدلیل استفادهاز NVIC_PRIORITYGROUP_4 که در برگه stm32f1xx_hal_msp.c در تابع HAL_MspInit مطابق عکس دوم مشخصشده ما باید آرگومان SubPriority را مساوی صفر قراردهیم و ازطریق آرگومان PreemptPriority اولویت وقفه را مشخصکنیم.
توجهداشتهباشید که درمورد بقیه وقفههای دیگر میکروکنترولر هم همین قضیه صادق است و ما میتوانیم ازطریق همین فرمانها آنها را فعال و غیرفعال کنیم و یا اولویت آنها را تغییردهیم. حال برایاینکه متوجهشوید چگونه میتوان لبه تحریک یک وقفه خارجی را تغییر داد، باید پیکرهبندی آن پین را دوباره انجامدهید. برای فهم بیشتر مسئله به عکسزیر توجهکنید:
حالا ممکناست این سوال پیش بیاید که مثلاً کلمه GPIO_MODE_IT_FALLING را از کجا آوردیم؟ راهحل آن ساده است بهتر است به محل تعریف آن برویم، در توضیح این موضوع یکبار دیگر هم این موضوع را تأکید میکنیم که برایاینکه به محل تعریفشدن یک ماکرو یا تابع برویم باید آنرا درحالت انتخابشده قراردهیم و سپس مانند عکسزیر روی آن کلیک راست کنیم و بعداز آن گزینه Go To Definition را بزنیم تا به محل تعریفشدن آن تابع یا ماکرو برویم.
در آن محل شما میتوانید مطابق عکسهایزیر، دیگر گزینههای مناسب برای جایگذاری را ببنید:
در قسمت ششم آموزش میکروکنترلر STM32 قصد داریم بااستفادهاز رجیسترها لبه وقفه خارجی را تغییر دهیم. پس با ما همراه باشید.
منبع: سیسوگ