Interrupt Öncelik Gruplanması Ve Interrupt Fonksiyonları

Güncelleme tarihi: 25 Kas




STM32F100RBT6B işlemcisi Cortex-M3’ün kesmelerden sorumlu birimi NVIC ile kesme öncelikleri gruplandırılabilinir. Yani programdaki main içinde loop şeklinde devam ederken kesme geldiğinde gelen kesmenin önceliğine göre o fonksiyon çalıştırılır.

Çevrebirimlerden gelen çeşitli kesme tipleri bulunmaktadır. Bu uygulamada harici kesmeler ve öncelik sıralaması (priority) incelenmiştir.

GPIO'lar 16 harici kesme (EXTI) hattına grup grup bağlıdır. Şekilde de görüldüğü gibi Örneğin PA0, PB0,PC0,PD0 EXTI0’a bağlıdır. PA2, PB2, PC2, PD2 ise EXTI2'ye bağlıdır.

EXTI yükselen veya alçalan kenarlarda veya hem yükselen hem alçalan kenarlarda aktif olabilir. (Rising Trigger, Falling Trigger.) Daha sonra interrupt isteği NVIC’e gider IRQ'ların etkinleştirilmesi/devre dışı bırakılması NVIC registerlarında yapılır.

Aşağıdaki şekilde de görüldüğü gibi NVIC ile kesme öncelikleri gruplanabilmektedir. Kesme öncelik registerlarının bir kısmı grup bitleri olarak kullanılırken bir kısmı alt grup öncelik bitleri olarak kullanılabilmektedir. Bir interrupt isteği gelince ilk olarak grup önceliğine bakılır. Aynı anda servis edilmesi gereken birden fazla interrupt varsa grup önceliği yüksek olan ilk servis edilir. (Örneğin 0 priority 1 priorityden daha önceliklidir.) Eğer birden fazla aynı grup önceliğine sahip kesme varsa da bu sefer alt grup önceliklerine bakılır. Eğer birden fazla servis edilmesi gereken kesmenin hem grup hem de alt grup öncelikleri aynı ise IRQ numarası daha düşük olan kesme ilk servis edilir.

Kesme isteği geldiğinde gerçekleşme öncelik sıralaması da belirlenince gerçekleştirilecek komutlar hangi linedan geliyorsa ona ait fonksiyonun içine yazılır. Örneğin Bir portun 0. pininden yani line 0'dan interrupt isteği geliyorsa bu istek geldiğinde çalışacak komutlar EXTI0_IRQHandler fonksiyonu içine yazılır. Bu linelara ait fonksiyonlar tablodaki gibi tanımlanmıştır


IRQ

Handler

Açıklama

EXTI0_IRQn

EXTI0_IRQHandler

Pin 0'lar için

EXTI1_IRQn

EXTI1_IRQHandler

Pin 1'ler için

EXTI2_IRQn

EXTI2_IRQHandler

Pin 2'ler için

EXTI3_IRQn

EXTI3_IRQHandler

Pin 3'ler için

EXTI4_IRQn

EXTI4_IRQHandler

Pin 4'ler için

EXTI9_5_IRQn

EXTI9_5_IRQHandler

Pin 5 ve 9 arası için

EXTI15_10_IRQn

EXTI15_10_IRQHandler

Pin 10 ve 15 arası için


Bu uygulamada 2 push buton kullanılarak, iki farklı interrupt isteği oluşturulmuş ve ledler iki farklı durum için yakılmıştır. İlk olarak ledler interrupt isteği gelmeden önce yanıp sönmektedir. Önceliği yüksek olan butonun prioritysi 0'dır. Bu butona basıldığında ledler EXTI0_IRQHandler(); fonksiyonuna girer. Önceliği daha düşük olan butonun prioritysi 1'dir. Bu butona basıldığında EXTI1_IRQHandler(); fonksiyonu çalışır. Şöyle ki önceliği düşük olan butona basıldığını varsayılırsa fonksiyon çalışırken, önceliği daha yüksek olana basıldığında önceliği düşük olan bu fonksiyonun içinden çıkılır ve önceliği yüksek olan fonksiyonun komutları çalıştırılır. Bu bitince önceliği düşük olana devam edilir. O da bitince program interrupt isteği gelmeden önceki işlemine kaldığı yerden devam eder.



Malzemeler:

  • Jumper kablolar

  • 3 Led

  • 2 Push buton

  • 2 direnç 220 ohm

  • STM32VL Discovery


Devre Şeması ve Kod:



#include "stm32f10x.h"                  // Device header
#include "stm32f10x_exti.h"             // Keil::Device:StdPeriph Drivers:EXTI



// 2 butonlu 3 ledli interrupt ornegi. Kesme isteklerine göre ledlerin yanma durumları değişiyor.
void gpioConfig(); // pinlerin ayarlanmasi
void extiConfig(); //kesme isleminin ayarlanmasi
void delay(); //gecikme fonksiyonu 


int main (){
gpioConfig();
extiConfig();

while(1){  // kesme istegi gelmeden önce ledler yanip sönmektedir
	
GPIO_SetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2);

	delay (360000);

GPIO_ResetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2);
	
	delay (360000);


}

}

void delay (uint32_t time){


while(time--);


}



void gpioConfig(){

	
	GPIO_InitTypeDef GPIOInitStructure; //pin ayarlari yapilacak
	
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE); // B portunun clock hatti aktif ediliyor 
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE);  //C portunun clock hatti aktif ediliyor
	
	GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP;  //B portunun pinlerinin modu push pull ayarlandi 
	GPIOInitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2; // B portunun 0 1 ve 2. pinleri çikis pini olarak ayarlandi
	GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz;// hiz ayari yapildi
	GPIO_Init(GPIOB,&GPIOInitStructure);// B portunun ayari yapildigi bildiriliyor
	
	
	GPIOInitStructure.GPIO_Mode=GPIO_Mode_IPD; // 2 buton kullanilacak modu pull down ayarlandi
	GPIOInitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1;  // C portunun 0 ve 1. pini buton icin kullanilacak
  GPIO_Init(GPIOC,&GPIOInitStructure); //C portunun ayari yapildigi bildiriliyor	 
	

}


void extiConfig(){


	EXTI_InitTypeDef EXTIInitStructure; //Harici kesmeler için ayarlama yapilacak
	NVIC_InitTypeDef NVICInitStructure; // NVIC kesme birimi ayarlari yapilacak
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //Harici kesme olacagi icin bagli olan clock hatti aktif hale getiriliyor
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource0); //1. kesmenin gerceklesecegi port ve pin 
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1); // 2. Kesmenin gerceklesecegi port ve pin 
	
  EXTIInitStructure.EXTI_Line=EXTI_Line0 | EXTI_Line1; //butonun biri PC0 pininde line0'da EXTI0,digeri	PC1 pininde line1'de
  EXTIInitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //exti modu interrupt olarak belirlendi
  EXTIInitStructure.EXTI_Trigger=EXTI_Trigger_Rising; // yükselen kenarda harici kesme olacak. 

	
	EXTI_Init(&EXTIInitStructure); //harici kesmelerin ayarlari yapildigi bildiriliyor
	
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //NVIC icin hangi grup kullanilacak o bildiriliyor

	NVICInitStructure.NVIC_IRQChannel=EXTI0_IRQn; // line0'dan harici kesme gelecek o bildiriliyor
	NVICInitStructure.NVIC_IRQChannelCmd=ENABLE; //fonksiyonlari aktif hale getirecek
	NVICInitStructure.NVIC_IRQChannelPreemptionPriority=0; //prioritysi düsük olanin önceligi daha fazladir. 0 oldugu icin oncelik daha fazla 
	NVICInitStructure.NVIC_IRQChannelSubPriority=0; //alt öncelik. priorityler esitse bakilir
	
	
	NVIC_Init(&NVICInitStructure); //nvic için ayar yapildigi bildiriliyor 
	
	NVICInitStructure.NVIC_IRQChannel=EXTI1_IRQn; //line1'de harici kesme gelecek o bildiriliyor
	NVICInitStructure.NVIC_IRQChannelCmd=ENABLE; // fonksiyonlari aktif hale getirecek
	NVICInitStructure.NVIC_IRQChannelPreemptionPriority=1; //prioritysi düsük olanin önceligi daha fazladir. 1 oldugu icin oncelik daha az 
	NVICInitStructure.NVIC_IRQChannelSubPriority=0; //alt öncelik. priorityler esitse bakilir
	
	NVIC_Init(&NVICInitStructure); //nvic için ayar yapildigi bildiriliyor 

}

void EXTI0_IRQHandler(){ // line 0da harici kesme gerceklesince calisacak olan fonksiyon

  if(EXTI_GetITStatus(EXTI_Line0)!=RESET){ //reset degilse ve line0'dan  istek geldiyse calisacak 
	  
 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); //kesmenin bittigi de bildirilmesi gerekiyor
	
}

}

void EXTI1_IRQHandler(){ // line 1'de harici kesme gerceklesince calisacak olan fonksiyon

	if(EXTI_GetITStatus(EXTI_Line1)!=RESET){ //reset degilse ve line1'den  istek geldiyse calisacak
	
	 for (int i=0; i<2; i++){ //kesme aninda ledler 2 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_Line1); //kesmenin bittigi de bildirilmesi gerekiyor


}
















Son Paylaşımlar