Arm 3: Stm32 GPIO register ayarları

Arm 3: Stm32 GPIO register ayarları

      Merhaba serimize GPIO çevre biriminin register seviyesinde kullanımı ile devam ediyoruz. GPIO'nun açılımından başlayabiliriz. GPIO'nun açlımı General-Purpose input/output yani genel amaçlı giriş ve çıkıştır. Yani GPIO, bir pini giriş,çıkış yada alternatif fonksiyon olarak kullanabilmemizi sağlayan bir yapıdır. Her kartın GPIO sayısı farklıdır ve GPIOlar'a atayabileceğiniz registerler bellidir. Bu bilgilere de kartın reference manualinden kolaylıkla ulaşabilirsiniz. Kullandığımız kartın pinout diagramı aşağıdaki gibidir.

      Görüldüğü gibi kullandığımız kartta P1 ve P2 olmak üzere iki sütun pin mevcut. Her sütunda A,B,C,D,E,H portlarından 0-15 arasında numaralandırılmış 16 tane pin bulunduğunu görüyoruz. Bunları aşağıdaki STM32CubeIDE programından almış olduğum pinout viewden görebilirsiniz.

       Her GPIO gördüğümüz üzere kullanım amaçları farklı ve programımıza göre farklı modlarda çalışabilmektedir. Aslında yukarıdaki pinout diagramında belirtilenler bu pinlerin alabileceği özel kullanımlar. STM32CubeIDE programında kartınızın pinout viewine bakarsanız orada tek tek pinleri ne amaçla kullanabileceğinizi görebilirsiniz. Mesela USART2 kullanmanız gereken bir projeniz var, bunun için D5 ve D6 pinlerini kullanmamız gerekmektedir.

Peki register seviyesinde GPIO'yu nasıl programlayacağız?

      Microdenetleyicilerde programlamak istediğimiz her bir çevre biriminin bir registerı vardır. Bu registera uygun sinyalleri vererek istediğimiz işlemleri gerçekleştirebiliriz. Reference manualde aşağıdaki resimdeki (sayfa 65) yere geldiğimizde, gördüğümüz üzere örneğin GPIOA'nın boundary addressine baktığımızda 0x4002 0000 - 0x4002 03FF olarak görüyoruz. Burada GPIOA için 32 bitlik registerlar bulunmaktadır.

      Reference manuale geri döndüğümüz zaman, bu sefer bakmamız gereken kısım GPIO registers (sayfa 281) olacak. Burada ilk karşımıza çıkan GPIO port mode register oluyor. Port mode registerın address offsetinin 0x00 olarak tanımlandığını görüyoruz. Burada bize tanımlamamız için 32 bitlik alan bırakılmış. Aşağıdaki tabloda görüldüğü üzere .

      Tablonun hemen aşağısında konfigürasyon bitlerini görmekteyiz. Buradaki bit değerlerini kullanarak pinlere atamalar yapıyoruz. Örneğin; A0 pinini alternatif fonksiyon olarak ayarlamak istiyorsak tablodaki Moder-0 kısmındaki atamaları 10 olarak yapıyoruz ve aşağıdaki gibi oluyor.

      Reference manuale baktığımız zaman GPIO port mode registerden sonra GPIO port output type registerın geldiğini görüyoruz. GPIO port mode register için 32 bitlik alan olduğunu söylemiştik. 32 bitlik alan 4 bayta tekabül etmekte. Bu nedenle GPIO port mode registerın address offseti olan 0x00'a 4 ekleyip 0x04'ü yani GPIO port output type registerın address offsetini elde etmiş oluyoruz. Aşağıda GPIO port output type registerın tablosuna baktığımız zaman sadece ilk 16 tablonun erişime açık olduğunu, diğer 16'sının ise rezerve olduğunu görüyoruz. Bunun nedeni buraya gireceğimiz verinin 2 bitlik değil tek bitlik olması.

      Bu kısımda yapabileceğimiz işlemle pinleri; output push-pull ya da output open-drain olarak ayarlayabiliyoruz. Geçen örnekte A0 pinini alternative fonksiyon olarak ayarlamıştık. Bu sefer de A0 pinini output open-drain olarak ayarlayalım ve aşağıdaki tabloyu elde edelim.

      Reference manuale bakmaya devam edersek bu yolla pinlerde değiştirebileceğimiz özellikleri görebiliriz. Böylece temel olarak GPIO'lara register seviyesinde atama yapmayı öğrenmiş olduk. Böyle register seviyesinde atama yapmak hem sürekli reference manual bakmayı gerektiriyor hem de yazımı uzun sürüyor. O nedenle genel olarak insanlar ya kendi kütüphanelerini oluşturuyor ya da hazır kütüphane kullanıyor. Bizim şuan kullanacağımız STM32CubeIDE programında hazır kütüphaneler var.

Register seviyesi kodlama

      STM32CubeIDE'de kartımızı yada kullandığımız işlemciyi seçip bir proje oluşturuyoruz. Oluşturduğumuz projenin main.c dosyasından main.h dosyasına geçiyoruz. Oradan bizim kartımızın spesifik tanımlarını görebiliriz.

      Örneğimizi kontrol etmesi daha kolay olsun diye led yakmayı seçtim. Burada kart üzerindeki ledlerin portlarını görebiliyoruz. Aşağıdaki resimde görüldüğü gibi ledler define olarak GPIOD'nin 12,13,14 ve 15. portlarına atanmış.

      Bizim ilk olarak GPIOD portuna clock sinyali vermemiz gerekiyor. Bunun için reference manualin 65. sayfasına baktığımız zaman, GPIOD'nin AHB1 clock busına bağlı olduğunu görüyoruz. Bu sayfa üzerinden 265. sayfadaki RCC register mape geçiyoruz. Burada bize lazım olan RCC_ AHB1ENR kısmını buluyoruz ve bize lazım olan GPIOD'yi enable yapıyoruz.

      GPIOD'yi yukarıdaki gibi enable yaptığımız zaman ortaya çıkan hexadecimal sayıyı hesaplıyalım ve devam edelim.

//AHB1ENR'yi atayabiliriz artık
RCC->AHB1ENR |= 0x8;

      Şimdi bizim GPIOD'nin pinlerini çıkış olarak ayarlamamız lazım. Bunun için reference manualin 281. sayfasına gitmemiz gerekiyor. Bu sayfada gördüğümüz üzere çıkış olarak ayarlamamız için "01" olarak atama yapmamız lazım pinlere.

//Burada yaptığımız 12,13,14 ve 15. pinler için 1 sayısını hexadecimal sistemde kaydırarak atama yapılmıştır
GPIOD->MODER |= (1 << 24); //12. pin için
GPIOD->MODER |= (1 << 26); //13. pin için
GPIOD->MODER |= (1 << 28); //14. pin için
GPIOD->MODER |= (1 << 30); //15. pin için

      Şimdi while döngüsü oluşturup işlemlere kaldığımız yerden devam edelim. Pinlerin output data registerlarına toogle işlemi yapmamız gerekiyor. Bunun için reference manualin 283. sayfasına göre atamamızı yapıyoruz.

GPIOD->ODR ^= (1 << 12); //12. pin için
GPIOD->ODR ^= (1 << 13); //13. pin için
GPIOD->ODR ^= (1 << 14); //14. pin için 
GPIOD->ODR ^= (1 << 15); //15. pin için

      Son olarak delay ekleyip bitiriyoruz.

#include <stm32f4xx.h>

int main (void)

{
	RCC->AHB1ENR |= 0x8;

	GPIOD->MODER |= (1 << 24); //12. pin için
	GPIOD->MODER |= (1 << 26); //13. pin için
	GPIOD->MODER |= (1 << 28); //14. pin için
	GPIOD->MODER |= (1 << 30); //15. pin için

	while (1)

	{
		GPIOD->ODR ^= (1 << 12); //12. pin için
		delay(500);
        GPIOD->ODR ^= (1 << 13); //13. pin için
		delay(500);
		GPIOD->ODR ^= (1 << 14); //14. pin için
		delay(500);
		GPIOD->ODR ^= (1 << 15); //15. pin için
		delay(500);
	}
}

      Bu makalemizin de sonuna gelmiş bulunmaktayız. Bir sonraki makalede görüşmek üzere.

      Saygılarımla.

STM32F4DISCOVERY - STMicroelectronics
STM32F4DISCOVERY - Discovery kit with STM32F407VG MCU * New order code STM32F407G-DISC1 (replaces STM32F4DISCOVERY), STM32F407G-DISC1, STMicroelectronics