Interrupt: İşlemcinin devam eden komutları bırakarak interruptın gösterdiği komutları yapması ve sonra bıraktığı komutlara kaldığı yerden devam etmesi olarak tanımlanabilir. Türkçe’de kesme olarak da kullanılmaktadır. CPU’ya içerden veya dışardan olmak üzere farklı kaynaklardan gelebilir. İşlemciyi oluşturan çevrebirimlerle haberleşmek ve programların uyumlu calışması için kesmeler kullanılır. Yazılım kesmeleri(software interrupts), donanım kesmeleri (hardware interrupts) olmak üzere iki tür kesme vardır. Yazılım interruptlarında makine komutlarıyla programa dahil edilen kesmeler vardır. Donanım interruptlarında bir çevre birim tarafından işlemcinin kesme biriminin aktifleşmesiyle gerçekleşir ve kesme olduğunda çalışacak program gerçekleşir. Donanım kesmeleri de kendi içinde ikiye ayrılır. Bunlardan ilki önlenebilir kesme (IRQ-Interrupt Request), ikincisi ise önlenemez kesme (Non-Maskable Interrupt-NMI) olarak tanımlanır. IRQ’de işlemcinin kesme birimine komut geldiyse kesme gerçekleşir, kesme talebi gelmediyse işlemci kendi işlerine devam eder, gerçekleşmez. NMI’de ise hiçbir zaman bir kesme isteğine bağlı değildir. Programcı tarafından önlenemezler.
İşlemcide NVIC (Nested Vectored Interrupt Controller) kesmelerden sorumlu birimdir. Arm çekirdeğine kesme gelince karşılayan ilk kısımdır. Cortx-M çekirdeğiyle birlikte kesmelerden sorumlu NVIC gelir. Bir tane de bunla birlikte calısan SysTick timer gelir, doğrudan çekirdeğe erişebilen bir timer. İşletim sistemi kullanılmasa da sıradan bir timer gibi kullanılabiliyor.
Kesmelerin ayarlarının yapılası için NVIC ve kesme hatlarının (örneğin kesme anında hangi port aktif olacak) ayarlarının yapılması gerekir. Bu uygulamada NVIC ve EXTI ayarlamaları yapılmıştır. Harici kesme hangi line'da gerçekleşecekse o belirlenmiştir. Ledler out olarak kullanılmış push butondan input bilgisi alınmış ve butona basıldığında ledler kendi çalışmasını bırakıp 4 kez yanıp sönmektedir. Bu yanıp sönme işlemi bitince de kendi işlemlerine kaldığı yerden devam etmektedirler.
Kartın user manuelinde bulunan blok diyagramda de görüldüğü gibi çevrebirimlerin kullanılması için clock hatlarının aktifleştirilmesi gerekmektedir. Örneğin bu uygulamada kullanılan B ve C portu APB2 clock hattına bağlıdır ve clock ayarı yapılmıştır. Yine aynı şekilde EXTI interruptun bağlı olduğu bus hattı da APB2 clocktur. Ayrıca yine blok diyagramda Cortex-M3 CPU işlemcisinin hemen altında NVIC birimi bulunmaktadır. Burası da işlemcinin kesmelerden sorumlu ve herhangi bir kesmeyi ilk karşılayan kısımdır.
Malzemeler:
Led
Jumper kablolar
STM32VLDISCOVERY
Push button
220 ohm direnç
Devre Şeması ve Kod:
#include "stm32f10x.h" // Device header
#include "stm32f10x_exti.h" // Keil::Device:StdPeriph Drivers:EXTI
// 3 tane led yanarken sirayla butona basildiginda interrupt da gerceklesiyor ve ledler ayni anda yanip sönüyor.
void gpioConfig(); //pinlerin ayarlamalarinin yapildigi fonksiyon
void extiConfig(); //interrupt ayarlamalarinin yapildigi fonksiyon
void delay(); //gecikme fonksiyonu
int main (){
gpioConfig(); //pinlerin giris cikis olarak ayarlanmasi fonksiyonu
extiConfig(); // interrupt ayarlamasi ve kesme gercekleseceginde hangi islem yapilacak onun ayarlari fonsiyonu
int ledArray[]={GPIO_Pin_0,GPIO_Pin_1,GPIO_Pin_2};
while (1){ // bu kisimda interrupt gerceklesmezken ledler sirayla yanip sonmektedir
for(int i=0;i<3; i++){
GPIO_SetBits(GPIOB,ledArray[i]);
delay(3600000);
GPIO_ResetBits(GPIOB,ledArray[i]);
delay(3600000);
}
for(int i=1;i>0; i--){
GPIO_SetBits(GPIOB,ledArray[i]);
delay(3600000);
GPIO_ResetBits(GPIOB,ledArray[i]);
delay(3600000);
}
}
}
void gpioConfig(){
GPIO_InitTypeDef GPIOInitStructure;
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE); //B portu için clock hatti aktif edildi ledler icin kullanilacak
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE); //C portu icin clock aktif edildi buton icin kullanilacak
GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //ledin push pull olarak kullanilacaginin ayari
GPIOInitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2; //ledlerin pinleri B portunun 0 1 ve 2. pinleri
GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz; //hiz ayari
GPIO_Init(GPIOB,&GPIOInitStructure);// B portundaki ayarlamalarin bildirilmesi
GPIOInitStructure.GPIO_Mode=GPIO_Mode_IPD; // buton input olarak kullanildi, pull down
GPIOInitStructure.GPIO_Pin=GPIO_Pin_0; // buton pinin baglandigi yer, C portu pin 0. Hiz ayarina gerek yok input oldugu icin
GPIO_Init(GPIOC,&GPIOInitStructure); // C portundaki ayarlamalarin bildirilmesi
}
void extiConfig(){ //kesmelerin ayarlamalarinin yapildigi fonksiyon
//2 structure olmali bir tanesi islemcinin kesme birimi NVIC digeri çevre birimlerden gelen harici kesme için EXTI
EXTI_InitTypeDef EXTIIinitStructure;
NVIC_InitTypeDef NVICInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // harici kesmelerin clock hatti aktif edildi
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource0); // hangi portta ve pinde gerceklesecekse interrupt bildirildi.
EXTIIinitStructure.EXTI_Line=EXTI_Line0; //kesmenin hangi lineda gerceklesecegi. Line0'da cunku C0 hatti line0'a bagli.
EXTIIinitStructure.EXTI_LineCmd=ENABLE;
EXTIIinitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTIIinitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTIIinitStructure); //EXTI ayarlarinin yapildigi bildiriliyor
NVICInitStructure.NVIC_IRQChannel=EXTI0_IRQn; // Interrupt gerceklesince hangi fonksiyon cagirilacak onu belirler, line 0'daki interrtupt calisacak
NVICInitStructure.NVIC_IRQChannelCmd=ENABLE; // Interrupt sirasinda fonksiyona gitmesi gerektigi
NVICInitStructure.NVIC_IRQChannelPreemptionPriority=1; //kesmenin öncelik sirasi
NVICInitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVICInitStructure); //NVIC ayarlarinin yapildigi bildiriliyor
}
void delay (uint32_t time){
while(time--);
}
void EXTI0_IRQHandler(){ // harici kesme gerceklestiginde calisacak olan fonksiyon. Ismı onceden belirli.
if(EXTI_GetITStatus(EXTI_Line0)!=RESET){// Line0'a gelen bilgi varsa yani reset degilse sürekli calissin
for (int i=0; i<4; i++){ //kesme aninda ledler 4 kez yanip sonsun
GPIO_SetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2);
delay (3600000);
GPIO_ResetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2);
delay (3600000);
}
EXTI_ClearITPendingBit(EXTI_Line0); // kesme süresi dolunca kesmenin bittigini de haber vermek gerekiyor.
}
}
Comments