30 Ağustos 2016 Salı

3 - STM32F4 ile Harici Kesme Kullanımı

Merhaba Arkadaşlar,
                Sıradaki örneğimiz Stm32f4 ile harici kesme nasıl yapılır bunun hakkında kısa bilgi ardından da kod paylaşımı yapılacaktır.
Kesme nedir? Niçin kullanılır hakkındaki bilgiyi internetten veya çeşitli kaynaklardan çok kolay bir şekilde anlaşılabilir. Burada bu konuya girilmeyecektir. Bu örnekten önce yine de bilmeyenler için herhangi bir kaynaktan bilgi edinmeleri gerekir.
Öncelikle STM32F4 işlemcisi 16 adet kesme kanalına sahiptir. Bu kanallar, her GPIO pininin 0’dan 15’e kadar olan pini kullanılabilir. Bunların isimleri de kullanılan pin numarası ile doğrudan ilişkilidir. Örneğin PA0 pini için kanal(0)’a bağlıdır. PA11 pini kanal(11)’e bağlıdır. Diğer portlar için de aynı şey geçerlidir. PE3 pini kanal(3)’e bağlı olarak tanımlanır.

4.kanala kadar kanallar tek bir kesme fonksiyonu ile çağrılabilir, ama 5,6,7,8 ve 9. pinleri bunlardan farklı bir kesme fonksiyonu ile çağrılır ve ayrıca 10’dan 15’e kadar olan pinler de ayrı kesme fonksyonu ile çağrılır. Aşağıdaki resimde daha net anlayacaksınızdır.


Yani PA0 da, PB0 da, PC0 da, PD0 da, PE0 da Line0 kanalına bağlıdır. Ancak sadece bir port kullanılabilir. Yani aynı anda kanal0 dan PA0,PB0 veya diğer 0.pinler kullanılamaz.
                Kesme kullanılacağı zaman kesme fonksiyonun ayarlamalarını da NVIC kodları ile yapılır. 0’dan 4’e kadar olan kesmeler kendi isimleri ile kesme fonksiyonu oluşturulurken, 5’den 9’a kadar olanların kesme fonksiyonlarının isimleri aynıdır. Aynı şekilde 10’dan 15’e kadar olan kesmeler de aynı şekildedir.

                Örnek olarak 0.kanaldan ve 11.kanaldan kesme örneklerini yapacağız.

Kodların çalışabilmesi için bazı kütüphanelerin sisteme eklenmesi gerekmektedir. Bunlardan daha önce eklediklerimiz olmuştu. Bunlar :  stm32f4xx.c,  stm32f4xx_gpio.c, stm32f4xx_rcc.c dosyaları idi. Ek olarak eklenmesi gereken kütüphaneler: stm32f4xx_exti.c, stm32f4xx_syscfg.c, misc.c  kütüphaneleridir. Peki bunlar nasıl eklenir? Daha önceki paylaşımlarda (sıfırdan proje oluşturma başlıklı paylaşım) bu gösterilmişti. Burada bunun hakkında bilgi yer alacaktır. Ancak yine de yapamayanlar ilk paylaşıma (sıfırdan proje oluşturma başlıklı paylaşım) bakarak yapabilirler.
Öncelikle programın solundaki Library klasörüne çift tıklayın:
Libraries -> STM32F4xx_StdPeriph_Driver -> src -> klasörlerine tıklayın ve gerekli olan (c) dosyalarını bulun ve ardından onları add butonuna basarak ekleyin. Bu dosyalar stm32f4xx_exti.c, stm32f4xx_syscfg.c, misc.c  dosyalarıdır. Daha önce bu dosyaların klasör adresleri belirtildiği için aynı işlemin tekrar yapılmasına gerek yoktur. Bu dosyalar eklendikten sonra kod yazımına başlanabilir.

0.kanal kesmesi:

İlk olarak kütüphaneler çağrılır:

#include "stm32f4xx.h"                             //stm32f4 kütüphanesi
#include "stm32f4xx_gpio.h"                    //GPIO kütüphanesi
#include "stm32f4xx_rcc.h"                      // RCC clock kütüphanesi
#include "stm32f4xx_exti.h"                     //harici kesme kütüphanesi
#include "stm32f4xx_syscfg.h"                 //systemcfg kütüphanesi
#include "misc.h"                                      //misc kütüphanesi

Daha sonra ana fonksiyon içerisinde konfigürasyon ayarları yapılır. Bunlar giriş çıkış pinlerinin ayarlanması ve kullanacağımız harici kesme konfigürasyon ayarlarıdır.
//Ana fonksiyon
int main(void)
{
                NVIC_InitTypeDef          NVIC_InitStructure;       //kesme için
                GPIO_InitTypeDef          GPIO_InitStructure;       // Port yönlendirmesi
                EXTI_InitTypeDef            EXTI_InitStruct;          // kesme için
               
  /* GPIOD Periph clock hatti aktif edilir */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
  /* Enable clock for SYSCFG */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  /* PD12, 13, 14 ve PD15 pinleri çıkış olarak kullanilacak */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;     //Pinler cikis olarak belirlendi
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     //Pin PushPull olarak ayarlandi
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;     //GPIO Bus hizi 100 MHz ayarlandi
  GPIO_Init(GPIOD, &GPIO_InitStructure);    //Yukarida tanimlanan bilgileri GPIOD adresine ait oldugu belirtilir

 /*harici kesme ayarlarinin yapilmasi*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                              //kesme pini PA0
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;                   //Pin giris olarak belirlendi
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;               //Pin PushPull olarak ayarlandi
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;     //GPIO Bus hizi 100 MHz ayarlandi
  GPIO_Init(GPIOA, &GPIO_InitStructure);           //Yukarida tanimlanan bilgileri GPIOA adresine ait oldugu belirtilir
               
/* EXTI_Line0 için sistemden PA0 pinini çagir*/
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);  /* EXTI_Line0'a PA0 baglandi  */
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;                                                          /* Enable interrupt */
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;                                                       /* Interrupt mode */
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;                               /* Triggers on rising and falling edge */
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;                                  
    EXTI_Init(&EXTI_InitStruct);                                                                                 /* Add to EXTI */
                /* kesme fonksiyonu için gerekli NVIC kodları*/
 NVIC_InitStructure.NVIC_IRQChannel        = EXTI0_IRQn ;                //kesme fonksiyonun ismi
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 0x00;        //farkli türler arasi oncelik
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;           //kendi turunun icindeki oncelik
 NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;
 NVIC_Init(&NVIC_InitStructure);
                                                                             
  while (1)            //Sonsuz donguye girilir
                               {                                            
                                              
                               }
}

Yukarıda programın ana fonksiyonu yapılmıştır. Şimdi sırada kesme fonksiyonunun yazılması gerekmektedir. NVIC kodları ile kesme fonksiyonunun ayarlamaları yapılmıştır. NVIC kodlarına bağlı olarak kesme fonksiyonunun ismi EXTI0_IRQHandler olmaktadır. Kesme fonksiyonu eğer ana fonksiyonun alt tarafına yazılacaksa yukarıda kesme fonksiyonunun ismi belirtilmelidir (void EXTI0_IRQHandler(void); ). Eğer ana fonksiyonun üst tarafına yazılacaksa gerek yoktur.

Kesme fonksiyonu:

void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line0) == 1)             //kesme pini 1 oldu mu?
       {
           EXTI_ClearITPendingBit(EXTI_Line0);         //kesme bayrağını temizle
           GPIO_ToggleBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
                /* PD12,13,14 ve 15. Pinleri TOGGLE yap*/
       }
}

Yukarıdaki kodda PA0 pinine bağlı bir kesme programı yapılmıştır. Eğer PA0 pinine dışarıdan bir etki olursa (yani 1 logic 1 değeri gelirse) PD12,13,14 ve 15. Pinleri toggle yapması istenmiştir. Kodlar derlenip daha sonra yükleme işlemi yapılabilir. STM32F4 discovery board kartına program yğklendiğinde butona basıldığında ledlerin 1 ise 0’a, 0 ise 1’e döndüğünü göreceksiniz.

Kodların resimleri aşağıdaki gibidir:



11.kanal kesmesi örneği: 

Kesme PB11 pinine bağlıdır.


Yukarıdaki resimde PB11 pinine bağlı kesme gösterilmiştir. Ek açıklamaya yukarıda yapıldığı için gerek duyulmamıştır.

İyi Çalışmalar.


                                                                                                                                    

1 yorum: