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
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