COIDE İLE NUCLEO-F401RE PROGRAMLAMA – Timer İnterrupt Kullanımı

Döngü içerisinde bayrak kontrolü ile yaptığımız led uygulamasında programımız başka herhangi bir işlem yapmadığı için led tersleme işlemi tam zamanında oluştu. Fakat daha karmaşık programlar yazdığımız zaman döngü içerisinde bayrak değişimini algılamada gecikmeler yaşanabilir. Led uygulamasında gecikmeler olması bir sıkıntı yaratmaz, ancak haberleşme yapan bir uygulama yazıyorsak milisaniyelik bir gecikme bile bütün haberleşmenin hatalı olmasına sebep olabilir. Bu gibi durumlarda interrupt kullanmamız gerekir.

İnterrupt kullanabilmek icin projemize misc.h kütüphanesini eklememiz gerekiyor.


#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
#include "misc.h"

void TIM2_IRQHandler(void);

int main(void)
{

/* GPIO init */
// LED PIN AYARI
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // A portunun saat darbesini aktifleştidik.

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 5 numaralı pin için ayarlıyoruz.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Pin çıkış tipini ayarladık.
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // Pinimizi output olarak ayarladık.
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // Pull Up direncini pasif yaptık.
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // Pinin maksimum çalışma frekansını ayarladık.
GPIO_Init(GPIOA, &GPIO_InitStructure); // Ayarları uyguluyoruz.

/* Timer interrupt ayarı */
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 10000 - 1; // 10000 darbe sayıyoruz. 10 Hz bir timer elde ettik.
TIM_TimeBaseStructure.TIM_Prescaler = 840 - 1; // 84 MHz saat frekansını 100 KHz'e düşürdük.
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM IT enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // timer interrupt aktifleştirdik.
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE); // timer aktifleştirdik.
while (1)
{
// Boş Döngü.
}

}// main sonu.

void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
GPIO_ToggleBits(GPIOA, GPIO_Pin_5); // Ledi tersliyoruz.
}
}

Timer ve interrupt ayarlarını yaptıktan sonra interrupt fonksiyonunu oluşturduk. Bir donanım çeşitli sebeplerle interrupt oluşturabilir. Örneğin timer, Update, Capture-Compare, Trigger gibi pekçok sebeple interrupt oluşturabilir. Hangi durumlarda interrup oluşturacağını ayar aşamasında TIM_ITConfig fonksiyonu ile ayarladık.

Fonksiyon içerisinde önce, oluşan interruptın timer update sebebiyle olup olmadığını kontrol ediyoruz. Update sebebiyle interrupt oluştu ise bayrağı temizleyip ledi tersliyoruz.

Görüldüğü gibi ana programımız boş bir while döngüsünden oluşuyor, ama çok yoğun bir program olsa da ledin çalışmasında bir değişiklik olmaz. Çünkü interrupt oluştuğu anda ana program interrupt fonksiyonuna atlayacak, fonksiyon içerisindeki kodu çalıştırdıktan sonra ana programa geri dönecektir. Böylece interrupt fonksiyonu içerisindeki işlemlerde herhangi bir gecikme olmadan gerçekleştirilir.

Proje dosyasını linkten indirebilirsiniz. –> coide_timer_interrupt_uygulamasi

Etiket(ler): , , , , , .Yer işareti koy Kalıcı Bağlantı.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir