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
}
Comments