STM32F4 Port Kullanımı


        Mikrodenetleyici elektriksel sinyaller için giriş ve çıkış olarak kullanılabilen port olarak adlandırılan 5(beş) set I/O(Giriş/Çıkış) pin’inee (her set 16 pin’dir) sahiptir.  Her bir I/O farklı sinyallerle kullanılabilecek farklı özelliklere sahiptir. Ek olarak, her I/O pin’i 16 tanımlı alternatif fonksiyondan bir tanesine sahiptir. Her iki özellik ve fonksiyonlar kullanıcı yazılımında mikrodenetleyici içerisindeki register’ların değeri değiştirilerek tanımlanabilir. Bahsi geçen özelliklerin ve alternatif fonksiyonların tek bir I/O pin’i için ayarlanmasını bu yazımızda paylaşacağız.

MODER ismi verilen mikrodenetleyici içerisindeki register’da her pin için 2(iki) bit bulunur. Port başına 16 pin bulunur, bu nedenle MODER 32-bit olmak zorundadır. Bu register reset durumundan sonra varsayılan değer olarak “00” değerini alır. Şimdi bu register’ın ilgili pin’ini temsil eden bit’lerin aldığı değerler ve anlamlarını inceleyelim.
“00” ise
Harici bir dijital sinyali mikrodenetleyici içerisine pin üzerinden almak için verilir. Kısaca pin giriş olarak tanımlanmıştır.
“01” ise
Dâhili olarak yazılım tarafından üretilen dijital sinyali pin üzerinden dış dünyaya aktarmak için verilir. Kısaca pin çıkış olarak tanımlanmıştır.
“10” ise
Pin’in alternatif fonksiyonlarının kullanılacağı belirtilir.
“11” ise
Pin’in analog sinyal için kullanılacağı belirtilir.

        I/O pinleri harici sinyaller için giriş olarak kullanıldığında farklı özelliklere sahip olacaktır.  Varyantlar en iyi Figür 1’deki blok diyagram incelenerek tanımlanabilir.

Figür 1. Portun tek bir pin’i için donanım yapılandırması

        Bu yapılandırma içerisinde çıkış sürücüleri pasif durumdadır ve I/O pin’i üzerindeki değer etkisidir. Giriş sinyali I/O pin üzerinden bağlanır ve her iki pull-up /pull-down dirençleriyle burada aktif edilir.
Mikrodenetleyici içerisinde pull-up/pull-down dirençlerini yapılandıran her pin için 2(iki) bit ayrılmış olan 32-bit genişliğinde PUPDR isimli bir register bulunmaktadır. Bu register’ın pin başına alabileceği değerler şöyledir.
“00” ise
Pull-up ve pull-down dirençleri pasif durumdadır. İlgili pin yüzer durumdadır (floating).
“01” ise
Pull-up direnci aktif ve pull-down direnci pasif durumdadır. Pin giriş durumunda lojik “1” yani high durumundadır.
“10” ise
Pull-up direnci pasif ve pull-down direnci aktif durumdadır. Pin giriş durumunda lojik “0” yani low durumundadır.

        Dijital sinyal TTL Schmitt Trigger bloğu üzerinden IDR adı verilen giriş veri register’ına girer. Pin üzerindeki değer yazılım tarafından IDR register üzerinden okunur. IDR register 16-bit uzunluğundadır. IDR register’ının bit-0’ı port’un pin 0’ına karşılık gelir.
Bir I/O pin mikrodenetleyici tarafından giriş ve çıkış sürücülerini aktif ederek çıkış olarak kullanıldığında farklı özelliklere sahip olur. Bu durumda hala IDR register’dan pin’deki değer okunabilir. Çıkış pin’i mikrodenetleyici içerisinde bulunan OTYPER isimli 16-bit register ile aşağıdaki gibi kullanılabilir.
“0” ise
Push-pull mod olarak çalışır. Pin üzerindeki sinyal low veya high yapılabilir.
“1” ise
Open-drain mod olarak çalışır. Pin üzerindeki sinyal sadece low yapılabilir. High yapabilmek için harici bir pull-up direnç bağlanabilir.

        Donanım çok hızlı çalışabilir fakat güce ihtiyaç duyar. Donanım hızı az güç harcayabilmek için örneğin pilli uygulamalarda her pin için ayarlanabilir. Mikro denetleyici içerisinde her pin’e 2-bit gelecek şekilde 32-bit genişliğinde OSPEEDR isimli bir register vardır. Reset durumunda bu register’ın değeri “00”dır. Mümkün olan hızlar OSPEEDR register ile ayarlanır. Bu değerler ve karşılıkları;
“00” ise
Low Speed 2MHz
“01” ise
Medium Speed 25MHz
“10” ise
Fast Speed 50MHz
“11” ise
High Speed 100MHz

        Figür 1’de gösterilen pin’deki sinyal değeri Output Data Register(ODR) üzerinden gelir. Bu register 16-bit genişliğindedir. Pin 0 bahsi geçen register’da bit-0’a karşılık gelir. ODR register’ın reset durumunda her bit’i 0 (sıfır) durumunu alır. Bu register yazılımcı tarafından yazılım içerisinde değiştirilebilir. ODR register içeriğini değiştirmek için yeni bir değeri direkt içerisine yazmanın dışında alternatif bir yol vardır. BSSR 32-bit register’dır. Bit-0’ına (LSB) high yani lojik “1” yazılırsa ODR register’ın bit-0’ı high yani lojik “1” görülecektir. Alternatif olarak, bit-16’ya lojik “1” yazıldığında ODR register’ın bit-0’ı low’a yani lojik “0”a gider. Yani 32-bit BSSR register’ın ilk 16 bit’inden biri lojik “1” yapılırsa ODR register’ın karşılık gelen bit’i lojik “1” olur. Sonraki 16 bit’den biri lojik “1” yapılırsa karşı gelen bit’i lojik “0” olur. Bu register bit’leri kullanılarak ODR register kontrol edilebilir.

        MODE register’dan alternatif fonksiyon seçildiğinde, çıkış sürücüleri 16 girişi olan multiplexer’ın çıkışına bağlanır. Multiplexer mikrodenetleyici donanımı içerisindeki alternatif sinyal kaynaklarından 16 taneden birini seçer. Multiplexer’ın seçimi için 4(dört) bit’e gereksinim duyulur. Bir port için alternatif fonksiyon tanımlamaları için 4 bit x 16 pin = 64 bit’e ihtiyaç duyulur ve bu bit’ler 2 (iki) adet 32 bit’lik AFRL ve AFRH ile adlandırılan register’larda bulunmaktadır. Her port bu register’lara ihtiyaç duyar (AFRL, AFRH). Bu register’ın alabileceği değerler ileriki bölümlerde detaylı bir şekilde açıklanacaktır. Standart I/O fonksiyonlarının yazılım ile aktif hale getirildiğinde bu register’ların varsayılan değeri 0 (sıfır)dır. Bu arada ilgilenen okuyucular RM0090 dokümanının bölüm 6 kısmını okuyabilirler.

        Port kullanan basit bir programı inceleyelim. Program buton değerini okur ve Led’i yakar. Buton E port’unda Led ise A port’undadır. Program ilk olarak port A ve port E’nin clock sinyallerini aktif eder ve kullanılacak olan port pin’lerinin tanımlanmasını gerçekleştirir. Son olarak buton okuma ve Led kontrolü için döngüye girer. Program figür 2’de gösterilmiştir.

#include "stm32f4xx.h"

void main (void) {                                   // program başlangıcı
char In;                                                  // giriş değerini okumak için kullanılan değişken tanımlaması
RCC->AHB1ENR |= 0x10 + 0x01;      // port A ve E’nin clock sinyalleri aktif edilir
GPIOA->MODER |= 0x00001000;     // MODE == OUT: LED =  PA06
while (1) {                                            // sonsuz döngü
In = GPIOE->IDR & 0x01;               // port E’nin pin 0’ında bulunan butonu In register’ına oku
If (In & 0x01)                                     // In register’ının bit 0’ı 1 mi kontrol et
GPIOA->ODR |= 0x0040;                // 1 ise Led’i yak
else                                                                      
GPIOA->ODR &= ~0x0040;           // 0 ise Led’i söndür
};
}
Figür 2
        Register ismi yukarı kodda belirtilen ve include edilen dosyada tanımlanmıştır. Kod içerisinde kullanılan GPIOA ismi port A’yı temsil eder. Bu tanımlamalar ve isimler stm32f4xx.h dosyasında bulunmaktadır.

        Program henüz belirtilmemiş AHB1ENR register’ına yazarak başlar. (AHB mikrodenetleyici içerisindeki AH bus, 1 register indeks numarası ve ENR enable register anlamına gelir). Mikrodenetleyici içerisinde karmaşık bir clock devresi mevcuttur. Bu register mikrodenetleyicinin içerisindeki clock dağılımlarını tanımlar. Aktif etme ve clock tanımlama ile ilgili birkaç register bulunur ve bu register’ların tümü Reset&Clock Control (RCC) olarak isimlendirilen blok içerisinde bulunurlar. Detaylar için RM0090 isimli teknik dokümanın Bölüm 5’ine bakabilirsiniz. Bir clock aktif değil ise diğer özellikleri değiştirmemek güvenlidir. AHB1ENR register’ının düşük 9 biti STM32F4xx mikro denetleyicisinin yüksek sürümlerinde 9 port’un clock’larını aktif etmek için kullanılır.

        Bu yazının başında portlar ile ilgili birden fazla register bulunduğunu söylemiştim. Fakat bunların varsayılan değerlerini bu basit örnekte kullanmak iyidir ve bu nedenle buraya dokunulmaz.
Lütfen register içeriklerinde değişiklik yaparken direkt olarak değiştirmeyin. OR kullanarak istediğiniz bit’i set edebilirsiniz. (örneğin RCC->AHB1ENR |= 0x10 + 0x01;). Bu teknik ile diğer bit’ler korunacaktır. Böylece register’ın önceki değeri bozulmayacaktır. Bit’leri resetlemek için AND fonksiyonu kullanılır ve kullanılan argüman terslenir. Böylece diğer bit’ler etkilenmezler.




#include "stm32f4xx.h"

void main (void) {
RCC->AHB1ENR |= 0x08;                          // GPIOD port’unun clock’unu aktif et.
GPIOD->MODER |= 0x00100000;              // MODE Register: bit 10 == Çıkış
while (1) {
for (int i=0; i<0x1000000; i++) {};              // zaman gecikmesi
GPIOD->ODR ^= 0x0400;                          // Toggle PD10
};
}
Figür 3. Port D’nin 10ncu bit’ine bağlı olan LED’i yakıp söndüren bir program.
Tek seferde birden fazla bit değiştirebilirsiniz. Figür 4’deki programda port D’ye 8-bit saydırılır.
#include "stm32f4xx.h"
void main (void) {
unsigned int i=0;                                                       // count değişkenini tanımlama
RCC->AHB1ENR |= 0x08;                          // GPIOD port’unun clock’unu aktif et.
GPIOD->MODER |= 0x00005555;              // MODE: en düşük 8 bit çıkış
while (1) {
GPIOD->ODR = i & 0x00ff;                        // port’un düşük 8 bit’İne gönder
i++;                                                               // sayacı arttır.
};
}

Figür 4. Port D’nin düşük 8 bit’ine counter sayacındaki değerleri gönderen program.

Şimdilik bu kadar arkadaşlar Gülen
Sorularınız ve önerileriniz için m.hakki.kaplan@gmail.com adresinden her zaman bana ulaşabilirsiniz.
Hakkı KAPLAN

Hiç yorum yok:

Yorum Gönder