وقفه خارجی یکی از ویژگی های اضافه شده به GPIO ها در حالت ورودی است. که باعث میشود میکروکنترلر روال فرآیندهایش را متوقف کند و به تغییرات اعمالی در پینهای ورودی توسط event ها یا trigger ها پاسخ فوری بدهد. در بسیاری از موارد استفاده از وقفه خارجی سودمند است. به عنوان مثال، دکمه اضطراری موجود روی تردمیل را در نظر بگیرید. شما با سرعت زیاد در حال دویدن هستید که ناگهان مچ پایتان درد میگیرد. مطمئناً شما در این حالت میخواهید بلافاصله متوقف شوید، به جای کاهش سرعت به صورت مرحله به مرحله، میتوانید دکمه اضطراری را بزنید تا تردمیل سریعاً متوقف شود. دکمه اضطراری تمام فرآیندهای دیگر را متوقف میکند و بلافاصله به CPU تردمیل دستور میدهد تا سرعت را سریعتر از حد امکان تغییر دهد. در واقع اولویت آن بالاتر از سایر فرآیندها میباشد.
اکثر میکروکنترلرهای 8 بیتی، پینهای وقفه خارجی کمی دارند و دارای محدودیت هستند، اما چنین محدودیتی برای میکروکنترلرهای STM8 وجود ندارد. در STM8، تقریباً تمامی پینهای GPIO دارای قابلیت وقفه خارجی با ورودی اشمیت تریگر هستند. علاوه بر این، کنترل کننده وقفه برای تعیین اولویت وقفهها وجود دارد.
حال با ارایه یک مثال به توضیح می پردازیم.می خواهیم با فشردن هر باز یک کلید متصل شده به PB5 ال ای دی متصل شده به PD3 تغییر وضعیت دهد.بدین منظور که اگر LED روشن بود با فشردن کلید خاموش و با فشار دادن مجدد آن کلید روشن گردد. اکنون باید ببینیم که چگونه باید وقفه را پیکربندی و کدگذاری کرد. این کد با تمام چیزهایی که قبلاً دیده اید متفاوت است و نیاز به توجه بیشتری دارد. چون بر خلاف کامپایلرهای دیگر شما باید گامهای خاصی را بردارید. در دیگر کامپایلرها، تنها چیزی که انجام میدادیم این بود که تابع وقفه را ایجاد کنیم و آدرس بردار وقفه را به کامپایلر بدهیم. در اینجا علاوه بر این کار مراحل دیگری را نیز باید انجام دهیم. جدول بردار وقفه برای STM8S003 در زیر نشان داده شده است:
این جدول را میتوانید در دیتاشیت آی سی با نام INTERRUPT MAPPING نیز پیدا کنید. این جدول برای هر آی سی متفاوت است پس مطمئن شوید که دیتاشیت آی سی مورد نظر خود را دریافت کردهاید. از آنجا که ما قصد داریم سوئیچ را به PB5 وصل کنیم پس باید از IRQ4 ، وقفه خارجی PORTB یا EXTI1 استفاده کنیم. تمام وقفههای خارجی روی پینهای GPIOB در این آدرس قرار گرفته است.
#include "stm8s.h" bool state = FALSE; int j; void GPIO_setup(void); void EXTI_setup(void); void clock_setup(void); void EXTI1_IRQHandler(void) { GPIO_WriteReverse(GPIOD, GPIO_PIN_3); } void main(void) { GPIO_setup(); EXTI_setup(); clock_setup(); GPIO_WriteReverse(GPIOD, GPIO_PIN_3); do { }while (TRUE); } void GPIO_setup(void) { GPIO_DeInit(GPIOB); GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_IN_PU_IT); GPIO_DeInit(GPIOD); GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST); } void EXTI_setup(void) { ITC_DeInit(); ITC_SetSoftwarePriority(ITC_IRQ_PORTB, ITC_PRIORITYLEVEL_0); EXTI_DeInit(); EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY); EXTI_SetTLISensitivity(EXTI_TLISENSITIVITY_FALL_ONLY); enableInterrupts(); } void clock_setup(void) { CLK_DeInit(); CLK_HSECmd(DISABLE); CLK_LSICmd(DISABLE); CLK_HSICmd(ENABLE); while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE); CLK_ClockSwitchCmd(ENABLE); CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1); CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE); CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE); }
تمامیه کد ها مانند مثال قبل می باشد با این تفاوت که در تابعی که قرار است نوع کاری که با وقوع اینتراپت یا همان وقفه انجام شود را قرار می دهیم.به شکل زیر:
void EXTI1_IRQHandler(void) { GPIO_WriteReverse(GPIOD, GPIO_PIN_3); }
و نیز قسمت مربوط به پیکر بندی یا همون تنظیمات مر بوط به وقفه که به شکل زیر انجام شده است.
void EXTI_setup(void) { ITC_DeInit(); ITC_SetSoftwarePriority(ITC_IRQ_PORTB, ITC_PRIORITYLEVEL_0); EXTI_DeInit(); EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY); EXTI_SetTLISensitivity(EXTI_TLISENSITIVITY_FALL_ONLY); enableInterrupts(); }
پاسخی بگذارید