STM32 - ARM Cortex M

STM32 – Register ile Multi EXTERNAL INTERRUPT

Herkese merhabalar, bu yazımda External Interrupt yani harici kesmeleri Register kütüphanesi ile işleyeceğiz. Ben STM32F407VG kartını kullanacağım burda,  sizler istediğiniz kartı kullanabilirsiniz ama dökümandan hangi faz hattına hangi EXTI bağlı buna dikkat edin , mesela D portunu açılırken  AHB1 üzerinden açılır  fakat STM32F100RB kartı APB2 üzerinden açılır bu yüzden dökümanıza göre hareket edin.

Bu bloğumuzda Registerları kullandık fakat and(&) ,or(|)  veya kaydırma(<<,>>) bitlerini kullanmadık bunun yerine Registerları Hexdecimal atamalar ile kullandık.

Kodlar yukardan aşağıya doğru tek tek açıklanarak gidildi ve en sonunda tamamı verildi.

Kütüphaneyi ekliyoruz
#include "stm32f4xx.h"

RCC  Yapılandırması için gerekli kodları giriyoruz. Bu kodları önceki bloğumuzda anlatık.
[button text=”Tıkla ve git” new_tab=”yes” size=”small” icon=”” url=”https://samettasoglu.com/2023/03/14/stm32f407vg-register-ile-system-clock-ayari/”]

GPIO Yapılandırması için gerekli kodları giriyoruz. Bu kodları önceki bloğumuzda anlatık.
[button text=”Tıkla ve git” new_tab=”yes” size=”small” icon=”” url=””]


EXTI Yapılandırması void EXTI_Config(void) adlı bir  fonksiyon oluşturuyoruz .

Bu fonksiyonun içerisine sırayla aşağıdaki kodları gireceğiz.

1-  RCC->APB2ENR = 0x00004000;
Bu kod ,  14. bit 1 yap demek yani  Clock Ayarlatında SYSCFG bitini (exti) enable yapıyoruz.

 

2- SYSCFG->EXTICR[0] = 0;
Bu kod, SYSCFG Registerinden  exti birimi için hangi port ve hangi pinden kesme alacağız onu seçtik.
EXTICR[hangi pin] = hangi port;

 

3- EXTIx_IRQHandler Fonksiyonlarını tek tek Aktif ettik .
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
NVIC_EnableIRQ(EXTI2_IRQn);

 

4-  EXTIx_IRQHandler Fonksiyonlarının tek tek  Önceliğini belirledik.
NVIC_SetPriority(EXTI0_IRQn,0);
NVIC_SetPriority(EXTI1_IRQn,1);
NVIC_SetPriority(EXTI2_IRQn,2);

 

5-  EXTI->IMR = 0x00000007;
Bu kod , 0. 1. 2.  pinleri Interrupt (KESME)  olarak ayarlar.

 

 

 

6-  EXTI->FTSR = 0x00000007;
Bu kod , 0. 1. 2.  pinleri Düşen Kenar olarak ayarlar.

 


 

EXTI_Config() fonksiyonun içerisine yazdığımız  kodlardan sonra her bir kesmede başlatılacak işlemin kodları için ayrı ayrı fonksiyon oluşturuyoruz.

void EXTI0_IRQHandler(void);
Bu kod, 1.kesmede devreye girecek fonksiyon.

1- if(EXTI->PR & 0x00000001);
Bu kod Pending Registerındaki  1. butondan kesme işleminin gelip gelmediğini kontrol ediyor eğer  Interrupt gerçekleşti ise  yani bayrak kalktı ise 0. bitden  ‘1’ dönüyor.
EXTI Registerındaki PR bitini kontrol ediyor, biz budu yazılımda if() yapısını kullanarak yapıyoruz.

2- GPIOD->ODR = 0x00001000;
Bu kod GPIOD Portunun,  ODR(Output Data) Registerindaki 12.Ledi yak demek. Siz burda istediğiniz işlemi yaptırtabilirsiniz.

3- EXTI->PR = 0x00000001;
Bu kod Pending Registerındaki 0. bitine 1  yaz demek . Yukarda bu biti kontrol ettik çünkü bayrağın kalkıp kalmadığını kontrol ettik burda ise 1 yaparak bu bayrağı tekrardan indirdik çünkü bayrak havada kalırsa bir sonraki kesmeye girdiğinde  sorun çıkabilir.

4- 

void EXTI1_IRQHandler(void);    –>  2.kesmede devreye girecek fonksiyon.
void EXTI2_IRQHandler(void);    –>  3.kesmede devreye girecek fonksiyon.
ve bunların kodları yukardakiler ile nerdeyse aynı tek fark müdahale edişen bit’ler farklı,  hadi bu kodları da inceleyelim.

2. kesme  için;
if(EXTI->PR & 0x00000002) ;         –> 2. biti if ile kontrol et eğer kesme oluşmuş ise if yapısının içerisine gir.
GPIOD->ODR = 0x00002000;                –> 13. led yansın, sizburda istediğiniz işlemi yaptırta bilirsiniz.
EXTI->PR = 0x00000002;                     –> Interrupt(kesme) için kalkan bayrağı tekrar indirdik.

3. kesme  için;
EXTI->PR & 0x00000004;                    –> 3. biti if ile kontrol et eğer kesme oluşmuş ise if yapısının içerisine gir.
GPIOD->ODR = 0x00004000;               –> 14. led yansın, sizburda istediğiniz işlemi yaptırta bilirsiniz.
EXTI->PR = 0x00000004;                   –> Interrupt(kesme) için kalkan bayrağı tekrar indirdik.

 


 

int main(void)  fonksiyonuna girip oluşturduğumuz Fonksiyonları burda çağıracağız ve sonra Ana döngüde olan kodumuzu yazacağız.

RCC_Config();
GPIO_Config();
EXTI_Config();

Ardından  while (1) fonksiyonunu açıp ana kodumuzu buraya yazıyoruz, ben yukardakiler gibi basit olsun diye 12. 13. 14. ve 15. ledleri belli bir süre yakıp söndüreceğim.

GPIOD->ODR = 0x0000F000;
for(int i=0; i<3600000; i++); // Bekleme
GPIOD->ODR = 0x00000000;
for(int i=0; i<3600000; i++); // Bekleme

 


 

Tüm Kod:

#include “stm32f4xx.h”

void delay(uint32_t time){
while(time–);
}

void RCC_Config(void) {

RCC->CR &= ~(1 << 0); // HSI off
RCC->CR |= (1 << 16); // HSE on, wait until ready
while (!(RCC->CR & (1 << 17)))
;
RCC->CR |= (1 << 19); // CSS on

RCC->PLLCFGR = 0; // PLL reset
RCC->PLLCFGR |= (1 << 22); // PLL source HSE
RCC->PLLCFGR |= (1 << 2); // PLL M=4
RCC->PLLCFGR |= (168 << 6); // PLL N=168
RCC->PLLCFGR |= (0 << 24); // PLL Q=Div2

RCC->CR |= (1 << 24); // PLL on, wait until ready
while ((RCC->CR & (1 << 25)) == 0)
;

RCC->CFGR &= ~(3 << 0); // SW0. ve SW1. bitleri sıfırladık
RCC->CFGR &= ~(0xF << 4); // (1111 << 4) ile aynı anlam 4. 5. 6. 7. bitleri yani AHB bitlerinin hepsini sıfırladık
RCC->CFGR |= (101 << 10); // 10. 11. 12. bite sırayla 1 0 1 bitlerini yerleştirdim – > APB1 = 4
RCC->CFGR |= (100 << 13); // 13. 14. 15. bite sırayla 1 0 0 bitlerini yerleştirdim – > APB2 = 2

RCC->CIR |= (1 << 19); // HSE Bayrağını indirir
RCC->CIR |= (1 << 20); // PLL Bayrağını indirir

}

void GPIO_Config(void) {

RCC->AHB1ENR |= 0x00000009; // A ve D Portu Aktif edildi
GPIOD->MODER |= 0x55000000; // 12. 13. 14. 15. ledleri OUTPUT olarak ayarladık ve defultda hepsi input bu yüzden 0. 1. 2. pinler input olarak ayarlı.
GPIOD->OTYPER |= 0x00000000; // hali hazırda kendisi reset modunda yapılamsada olur yani giriş ve çıkışlar için tanımlı
GPIOD->OSPEEDR |= 0xFF00003F; // 12. 13. 14. 15. ledlerin VE 0. 1. 2. pinlerin hepsini high speed yaptık
GPIOD->PUPDR |= 0x0000002A; // 0. 1. 2. bitler Pull-Down olsun geri kalanlar No-PD No-PU olsun
}

void EXTI_Config(void){

RCC->APB2ENR = 0x00004000; // 14. bit 1 YAP ; Clock Ayarlatında SYSCFG bitini (exti) enable yap
SYSCFG->EXTICR[0] = 0; // syscfg’nin exti birimi için hangi port ve pin den kesme alacağız onu seçtik. 0x00000000 -> A portu
// EXTICR[hangi pin] = hangi port;

// EXTIx_IRQHandler Fonksiyonlarını Aktif ettik
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
NVIC_EnableIRQ(EXTI2_IRQn);

// EXTIx_IRQHandler Fonksiyonlarını Önceliğini belirledik
NVIC_SetPriority(EXTI0_IRQn,0);
NVIC_SetPriority(EXTI1_IRQn,1);
NVIC_SetPriority(EXTI2_IRQn,2);

 

EXTI->IMR = 0x00000007; // 0. 1. 2. Pinleri Interrupt olarak ayarladık
EXTI->FTSR = 0x00000007; // 0. 1. 2. Pinleri düşen kenar olarak ayarladık

}

// 0. Pin ile kesmeye girecek fonksiyonn
void EXTI0_IRQHandler(void){
if(EXTI->PR & 0x00000001){ // Interrupt’a girdimi diye kontrol et , 0. register 1 mi?
GPIOD->ODR = 0x00001000; // 12. ledi yak
delay(1680000); // bekle
EXTI->PR = 0x00000001; // aynı Regsiterın aynı bitini 1 yap ; 1 yaparak kalkan bayrağı indirdik.
}
}

// 1. Pin ile kesmeye girecek fonksiyon
void EXTI1_IRQHandler(void){
if(EXTI->PR & 0x00000002){ // Interrupt’a girdimi diye kontrol et , 1. register 1 mi?
GPIOD->ODR = 0x00002000; // 13. ledi yak
delay(1680000); // bekle
EXTI->PR = 0x00000002; // aynı Regsiterın aynı bitini 1 yap ; 1 yaparak kalkan bayrağı indirdik.
}
}

// 2. Pin ile kesmeye girecek fonksiyon
void EXTI2_IRQHandler(void){
if(EXTI->PR & 0x00000004){ // Interrupt’a girdimi diye kontrol et , 2. register 1 mi?
GPIOD->ODR = 0x00004000; // 14. ledi yak
delay(1680000); // bekle
EXTI->PR = 0x00000004; // aynı Regsiterın aynı bitini 1 yap ; 1 yaparak kalkan bayrağı indirdik.
}
}

int main(void)
{
RCC_Config();
GPIO_Config();
EXTI_Config();

while (1)
{
GPIOD->ODR = 0x0000F000;
for(int i=0; i<3600000; i++);
GPIOD->ODR = 0x00000000;
for(int i=0; i<3600000; i++);
}
}

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu