1- ARM Mimarisi İşlemci tasarımları 2 farklı mimaride dizayn edilir. Bunlar CISC (complex instruction set computer) ve RISC (reduced instruction set computer) mimarileridir. CISC mimarisi programlanmasının kolay olması, etkin bellek kullanımı sağlaması (değişken uzunluklu ve karmaşık yapılı komutlar içermesi bellek tasarrufu sağlar), geriye doğru uyumlu olması, mimari yapısındaki *mikrokod komut gruplarını içeren ROM belleğe komutların eklenmesi ile CPU nun yapılması gereken işler için daha az zaman harcaması, derleyicilerin karmaşık olmaması gibi avantajların yanı sıra CPU yapısının yeni işemciler için karmaşıklaşması, eklenen farklı komutların farklı saat çevrim sayısına gerek duymaları ve performans düşüşü görülmesi, özel komutların programlarda çok fazla kullanılmamaları gibi dezavantajları da bulunmaktadır. *Mikrokod; CISC mimarisine sahip işlemcilerde, komut kodlarına karşılık gelen mikrokod komut grupları vardır. Bu komut grupları için özel bir ROM bellek mevcuttur ve yeni komutlar bu belleğe eski komutların üzerine yazılır. RISC mimarisi, CISC mimarisinin meydana getirdiği karmaşıklığı önlemek için ortaya çıkmıştır. RISC mimarisinde tüm komutlar tek çevrimde çalıştırılır böylece performans düşüşü gözükmez. RISC mimarisinde belleğe sadece Load ve Store komutları ile erişilir ve tüm komutlar mikrokod kullanmadan çalıştırılır. Bu sayede RISC mimarisinde komut kümeleri küçültülmüştür böylece daha hızlı çalışmakta ve az sayıda yonga kullanmaktadırlar. Ayrıca yüksek seviyeli dilleri desteklemesi ve çok sayıda register a sahip olması diğer avantajlarındandır. ARM (Advaced Risc Machine) mimarisi kısa komut setlerinden oluşan RISC tabanlı gelişmiş bir mikro kontrol mimaridir. Yani bir işlemci değil mimaridir. Kısaca işlemci, chip üreten firmalara işlemci mimarisi tasarlayan ARM firmasının geliştirdiği bir mimaridir. ARM mimariye sahip işlemciler, düşük güç tüketimi, yüksek performans, düşük fiyat gibi özelliklerinden dolayı günümüzde en çok kullanılan işlemcilerdir. En yaygın kullanım alanı 32 bit işlemcilerdir. Cep telefonları, taşınabilir cihazlar, avuç içi bilgisayaralar (pda), medya oynatıcıları, hesap makineleri, disk sürücüleri ve çeşitli elektronik cihazlarda arm işlemciler kullanılmaktadır. ARM mimari ailesi 3 temel gruptan oluşmaktadır. Bunlar klasik ARM işlemciler (ARM7, ARM9, ARM11), gömülü sistem ARM işlemcileri (cortex m serisi) ve uygulama ARM işlemcileri (cortex a serisi) dir. İnceleyeceğimiz STM32F4 Discovery ARM Cortex M4 mimarisine sahiptir. Cortex serisi işlemcilerde clock kaynağı olarak kristal osilatör, dahili RC osilatör yada harici bir kaynak kullanılabilmektedir. Güç tüketimini kontrol edebilmek için, çevre birimlerinin clock sinyalleri tamamen kapatılabilir, buda güç tüketimini oldukça azaltan önemli bir özelliktir. Ayrıca bu serideki işlemcilerde DMA
(direct memory Access) donanımı sayesinde bir yada sıralı adreslerden okunan veriler, bir başka adrese yada sıralı adreslere CPU gücü kullanılmadan taşınabilir. DMA donanımı verileri CPU dan peripheral-memory, memory-peripheral, peripheralperipheral, memory-meory yolları ile hızlı bir şekilde kaynak adresten hedef adrese gönderme işlemini gerçekleştirir. Bu sayede CPU üzerine düşen iş yükü azaltılmış olur. ARM mimari ailesi [1] ARM mimarisine sahip işlemcileri programlamak için farklı derleyiciler mevcuttur. Ancak bu kitap boyunca incelenecek olan STM32F4 kiti ile arm işlemcilerin nasıl programlandığını göreceğiz ve tek bir derleyici (keil) ile çalışmalarımızı yapacağız. 2- STM32F4 Discovery Kit İncelemesi STM32F4 Discovery kiti üzerinde ARM Cortex M4 tabanlı 168 MHz lik bir mikrodenetleyici (STM32F407VGT6) bulunmaktadır. ARM Cortex M4 mimarisi DSP (sayısal işaret işleme) fonksiyonlarını içeren, üzerinde ondalıklı işlemler için tasarlanmış ek bir birim olan FPU (floating point unit) ünitesini barındırmaktadır. Kit incelendiğinde üzerinde mikrofon, kulaklık girişi ve hareket sensörü dikkati çekmektedir. Bu kartın DSP fonksiyonlarını içermesi ile ilgilidir. Kit üzerindeki donanımların fazla olması işimizi oldukça kolaylaştırmaktadır. Mesela mikrofondan alınan sesi dijital veri haline çevirmek için I2S (Inter IC Sound bus) protokolü veya DAC kullanılabilmektedir. Yada kart üzerindeki ivmeölçerden veriler SPI yada I2C ile okunabilmekte hatta kart üzerindeki ledler ivmeölçerin durumuna göre de yanıp sönmektedirler.
STM32F4 Discovery donanım şeması [2] 2.1. STM32F4 Discovery Donanım 32-bit ARM Cortex-M4F çekirdeğine sahip STM32F407VGT6 mikrodenetleyicisi, 1 MB Flash ve 192 KB RAM Dahili ST-LINK/V2 JTAG Debugger USB veya harici kaynaktan doğrudan 5v ile çalışabilme 3 ve 5 V çıkış pinleri ST MEMS hareket sensörü 3-eksen dijital ivmeölçer (LIS302DL) Omni-Directional Mikrofon (MP45DT02) CS43L22 entegre D sınıfı yükselteçli ses sürücüsü Sekiz adet LED: USB haberleşmesi için : LD1 (kırmızı/yeşil) 3.3 V power on/off ledi (LD2: kırmızı) Dört adet kullanıcı ledi, LD3 (turuncu), LD4 (yeşil), LD5 (kırmızı) ve LD6 (mavi) 2 adet USB OTG ledi, LD7 (yeşil) ve LD8 (kırmızı) Bir adet Reset butonu Bir adet kullanıcı için buton USB OTG için mikro-ab konektör. 100 adet pinin tamamını kullanabilmeye imkan tanıyan çıkışlar.
3. Keil Derleyicisinin Kurulumu Bu kitap boyunca, STM32F4 Discovery kitine program atmak için yada kod yazıp derlemek için keil derleyicisini kullanacağız. Keil derleyicisi ücretsiz sürümünü https://www.keil.com/download/ adresinden çıkan formu doldurarak indirebilirsiniz. Bu ücretsiz sürüm 32KByte uzunluğuna kadar program yazılmasına müsaade eder. Bu da şu anda bizim için yeterlidir. İndirilen mdk_5xx.exe dosyası keil derleyicisinin setup dosyasıdır. Bu dosya ile kuruluma başlanır. Bu işlem biraz uzun sürmektedir. Bu işlemin sonunda Pack Installer isminde bir dosya açılacaktır. Buradan Keil:STM32F4xx_DFP paketi yüklenmelidir (Şekil 3.1). Şekil 3.1 Keil derleyicisin kurulumu bittikten sonra driver yükleme işlemi yapılır. ST Link driverı http://www.st.com/web/en/catalog/tools/pf258167 adresinden yüklenebilir. ST Link ile STM32 geliştirme kartlarına program atılabilmektedir. STM32F4 kartı bilgisayara takıldığında Aygıt Yöneticisi kısmında STMicroelectronics STLink dongle ismi ile gözükmelidir (Şekil 3.2). Eğer bu şekilde gözükmez ise sürücü tekrar yüklenmelidir.
Şekil 3.2 Keil derleyicisinde yapmamız gereken bazı ayarlar mevcuttur. Bunları Şekil 3.3 deki Options for Target kısa yolundan yada Araç menüsü kısmından sırasıyla Project- Options for Target seçenekleri ile açtığımız pencerede yapacağız (Şekil 3.4). Şekil 3.3
Şekil 3.4 Açılan bu pencerede yapılması gereken ayarlar şu şekildedir: Device-STMicroelectronics-STM32F4 Series-STM32F407-STM32F407VGTx seçilir. Target seçeneği seçildiğinde IROM1 karşısında 0x8000000 adresi vardır. Bu programın ilk çalıştırıldığında bu adresten başladığını gösterir (Şekil 3.5) Şekil 3.5
Debug linki altında ST-Link Debugger seçilmelidir. Bu direkt kart üzerinde çalıştığımız durumlarda yapılması gereken bir ayardır (Şekil 3.6). Eğer simülatörde çalışmamız gerekirse Use Simulator seçeneği seçilmelidir. Şekil 3.6 Debug seçeneği altında Settings linkine tıklandığında Debug-Port kısmında SW seçili olmalıdır (Şekil 3.7). Trace Core Clock : 168.000000 MHz olarak değiştirilmelidir. Şekil 3.7
Debug Settings- Flash Download seçenekleri altından Add- STM32F4xx Flash seçilir (Şekil 3.8). Şekil 3.8 Utilities seçeneğinden ST-Link Debugger seçilmelidir (Şekil 3.9). Şekil 3.9
4. Blinky Programının Çalıştırılması İlk Uygulama Keil derleyicisini kurduğumuzda birkaç tane hazır programda birlikte yüklenmektedir. Bu programlar derleyicinin yüklendiği dosya içerisindeki ARM-Boards-ST-STM32F4 DISCOVERY-Blinky klasörü içerisindedir. Eğer bu şekilde bir klasör oluşmamışsa yani örnekler yüklenmemişse Keil programından Pack Installer açılarak örnekler yüklenir (Şekil 4.1). Şekil 4.1 Örnek led yakıp söndürme programımızı yüklediğimize göre artık çalıştırabiliriz. Keil programı açılır. Project-Open Project seçenekleri ile indirilen uvision uzatılı Blinky projesi seçilir ve ekranda kodlar gözükür (Şekil 4.2).
Şekil 4.2 STM32F4 Discovery kiti bilgisayara usb yardımı ile bağlanır. Keil derleyiciden sağ üst kısımdaki Rebuild kısa yoluna tıklanarak program derlenir. Alt kısımdaki uyarı panelinde \Flash\Blinky.axf" - 0 Error(s), 0 Warning(s). Buna benzer bir mesaj gözükmelidir. Bu derleme işleminin başarılı olduğunu ve programda hata olmadığını göstermektedir. Sonrasında Load kısayolu ile geliştirme kitine program yüklenir (Şekil 4.3). Load tuşuna basıldığında kit üzerindeki LD1 ledi yeşil kırmızı olarak yanıp sönecektir. Led sabit kırmızıya döndüğünde kodların yüklendiği anlaşılmaktadır. Alt kısımdaki uyarı panelinde şu şekilde bir mesaj gözükmelidir: Programming Done. Verify OK. Application running... Flash Load finished at 05:42:40 Herşey yolunda ise geliştirme kiti üzerindeki 4 adet led sırasıyla yanıp sönecektir. Şekil 4.3
4.1. Blinky Programı Kod İncelemesi ARM tabanlı işlemcilerde program akışını bu örnek üzerinde anlatacağız. Dolayısıyla yapacağımız diğer örneklerde de program akışı bu şekilde olacaktır. Program ilk olarak genel ayarların bulunduğu startup dosyasından çalışmaya başlar. Genel ayarlardan kastımız vektör tabloları, *stack büyüklüğü, memory üzerinde nelerin okunacağı, giriş çıkış birimleri gibi ayarlamaların yapıldığı temel başlangıç ayarlarıdır. Bu dosyaya Keil programında sol kısımdan Device-startup_stm32F407xx.s (Startup) seçenekleri ile ulaşılır. Program startup dosyası içerisinde ilk olarak Reset handler kısmını çalıştırır (Şekil 4.4). Reset Handler kod kısmı CPU resetlendikten sonra çağrılan kısımdır. Kod blokları içerisinde de görüldüğü gibi IMPORT SystemInit ve IMPORT _main komutları ile SystemInıt ve main foksiyonları import edilmişlerdir. LDR komutu ile SystemInit fonksiyonu reset işlemi sonunda çağırılır ve peşinden main fonksiyonu çağrılır. Şekil 4.4 *stack nedir? Stack Türkçe olarak yığın bölgesi anlamına gelmektedir. Mikroişlemcilerde alt programları çağırdığımız zaman geri dönüş adresini sakladığımız RAM bellekte ayrılan kısımdır. Mikroişlemcilerdeki PUSH ve POP kodları buna örnektir. PUSH komutu ile kullandığımız
register bir stack de saklanır, böylece POP komutuyla verimizi tekrar çağırdığımızda aynı registıra bu veri konulur. Startup dosyası içerisinde önemli olan diğer kısımda üst kısımdaki vektör tablosudur (Şekil 4.5). ARM işlemcilerin tamamında vektör tablosu bulunmaktadır. Vektör tablosunda, stack pointerların reset değerleri, başlangıç adresleri, interruptlar bulunmaktadır. Özellikle interrupt kullandığımız durumda vektör tablosunu kullanarak interrupt fonksiyonlarını belirleyip isimlendireceğiz. Şekil 4.5 Startup dosyası içerisinde reset handler kısmında 2 fonksiyondan bahsetmiştik (SystemInit ve main fonksiyonları). Dolayısıyla bu fonksiyonu.c uzantılı dosya içerisinde oluşturmalıyız. Blinky kodunu incelediğimiz için bu aşamada bu fonksiyonu biz oluşturmayacağız. İleriki örneklerde nasıl yapıldığına değineceğiz. Bizim örneğimizde bu fonksiyon Device seçeneği alıtndaki system_stm32f4xx.c (Startup) dosyası altındadır (Şekil 4.6). Bu fonksiyon içerisinde clock ayarları, I/O (giriş/çıkış) ayarları, interrupt ayarları vs. yapılmaktadır.
Şekil 4.6 SystemInit fonksiyonundan sonra çağrılan main fonksiyonu bu örneğimizde Blinky.c dosyası içerisindedir (Şekil 4.7). Bu fonksiyon altında esas kod kısmı yer alır. Programımızın ne yapması gerektiğini bu kısma yazacağız. Şekil 4.7 Genel olarak ARM işlemcilerin nasıl programlandığını görmüş olduk. Artık kodların nasıl yazılacağını komutların ne anlama geldiğini kendi yazacağımız kod ile adım adım inceleyelim.
5. STM32F4 Discovery Led Açma Kapatma Uygulaması Direk kod yazımına geçmeden önce öğrenmemiz gereken komutlar bulunmaktadır. Bu komutları inceleyelim: GPIO : ARM işlemcilerde herbiri 16 bit olan 5 farklı GPIO (GPIOA, GPIOB, GPIOC, GPIOD, GPIOE) bulunmaktadır. GPIO pinleri kullanıma bağlı olarak giriş/çıkış (I/O) portu olarak ayarlanabilir ve her GPIO portunun 32 bit değerinde kontrol registerı 2 tanede data registerı bulunur. Kontrol registerları, GPIOx_MODER (port mode register), GPIOx_OTYPER (output tip register), GPIOx_OSPEEDR (output speed register), GPIOx_PUPDR (*pull up/pull down register) diye ismlendirilirler. Data registerları GPIOx_IDR ve GPIOx_ODR dir. Ayrıca 32 bir set/reset registerı (GPIOx_BSRR), 32 bit kilit registerı (GPIOx_LCKR) ve 2 adet 32 bitlik alternatif fonksiyon seçme registerı (GPIOx_AFRH, GPIOx_AFRL) bulunur. *pull-up / pull-down: Pull up, pin giriş olarak ayarlandığında ve pine herhangi bir sinyal gelmediğinde, girişi HIGH olarak ayarlar. Çıkış olarak kullanıldığında ise, pine herhangi bir çıkış sinyali verilmediğinde, pini HIGH olarak ayarlar. Pull down ise pin giriş olarak ayarlandığında ve pine herhangi bir sinyal gelmediğinde, girişi LOW olarak ayarlar. Çıkış olarak kullanıldığında ise, pine herhangi bir çıkış sinyali verilmediğinde, pini LOW olarak ayarlar. GPIO I/O olarak kullanıldığında 16 bitte kontrol edilebilir. Pinlerin giriş yada çıkış olarak kullanılması GPIOx_MODER kontrol resgiterı ile ayarlanır. Kontrol registerı 32 bitti yani her 2 bit bir GPIO pinine bağlıdır. 00 giriş, 01 çıkış, 10 alternatif görev, 11 analog mod olduğunu gösterir. Bunu bir örnekte gösterelim. GPIOx_OTYPER kontrol registerı output olarak tanımlanmış pinin çıkış değerini ayarlar. 0 ise *push pull, 1 ise *open drain olarak ayarlanır. *push-pull : Çıkışı lojik 1 olarak ayarlar. *open-drain : Çıkışı grounda bağlar. Bunun kullanılma amacı, işlemcinin pin çıkışından kontrol edilemeyen yüksek akım çeken harici aygıtların kontrol edilebilmesini sağlamaktır. Bu işlem için harici pull up dirençleri eklenmelidir.
GPIOx_OSPEEDR kontrol registerı output pinlerinin hızını ayarlar. Bunu frekansı ayarlayarak yapar. 00 2 MHz ve altı, 01 25 MHz ve altı, 10 50 MHz ve altı, 11 100 MHz ve altı olduğunu gösterir. GPIOx_PUPDR kontrol registerı pull up/ pull down ayarlarının yapılması için kullanılır. 00 pull up ve pull down direncinin olmadığını, 01 pull up direncinin olduğunu, 10 pull down direncinin olduğunu, 11 yedek (reserved) olduğunu gösterir. Giriş data registerı (GPIOx_IDR ) pin girişinin lojik 1 (HIGH) yada lojik 0 (LOW) olduğunu gösterir. Yani pin değerini okuyan registerdır. Bit değerlerinde karşılıkları şu şekildedir: 0 high lojik, 1 low lojik. Çıkış data registerı (GPIOx_ODR ), pin çıkışını ayarlar. 0 high lojik, 1 low lojik değerlerine karşılık gelir. Kilit registerı (GPIOx_LCKR), registerların kilitlenmesi yani değerinin resetleninceye kadar değiştirilememesini istediğimiz durumlarda kullanılır. Yeni Proje Dosyası Oluşturma Keil programında yeni bir proje dosyası oluşturma şu adımlar takip edilerek yapılmaktadır: 1. Keil programı açılır. File menüsünden New uvision Project seçilir. 2. Proje istenilen klasöre proje adı girilerek kaydedilir. 3. Karşımıza çıkan ekrandan işlemci seçimi yapılır. Biz STM32F4 Discovery kullandığımız için STM32F407VG işlemcisini seçeriz (Şekil 5.1).
Şekil 5.1 4. Ok dedikten sonra startup dosyalarını eklememiz gereken bir pencere açılacak. Bu penecereden Device sekmesinden startup seçilir. Sonrasında CMSIS sekmesinden CORE seçilir ve OK butonuna tıklanır (Şekil 5.2). Not: Keilin eski sürümlerinde bu işlem bir mesaj ile yapılıyordu ve Evet denildiğinde startup dosyası oluşturuluyordu.
Şekil 5.2 5. Açılan proje dosyasının sol kısmından Target sekmesinin + butonuna basılır. Source Group sekmesi gözükecektir (Şekil 5.3). Şekil 5.3 6. Source Group sekmesine sağ tıklanıp Add new item to group.. seçeneğine tıklanır. Açılan pencereden C File (.c) seçilir ve oluşturulacak.c dosyasının adı yazılır (Şekil 5.4). Şekil 5.4
7. C dosyasını da oluşturduktan sonra Keil programında debugger ayarlarını yapmamız gerekir. Bu kısmı yukarıda anlatmıştık. Ancak tekrar etmekte ve bütün halinde sistemi tanımakta fayda var. 8. Project yada bu kısayol kullanılarak Option for Target penceresi açılır. Bu pencerenin Target sekmesinden Xtal kısmını 8 MHz olarak ayarlarız (Şekil 5.5). Çünkü xtal harici osilatördür ve bu bizim işlemcimizde 8 MHz değerindeki kristaldir. dir. Şekil 5.5 9. Aynı pencereden Debug sekmesine tıklanır ve Use: ST-Link Debugger seçilir (Şekil 5.6).
Şekil 5.6 10. Aynı sekme altından Settings seçilir. Açılan pencereden Debug sekmesi altında Port SW olarak değiştirilir (Şekil 5.7). Şekil 5.7 11. Aynı pencereden Trace sekmesi altında Core Clock ayarı 168.000000 olarak değiştirilir (Şekil 5.8).
Şekil 5.8 12. Flash Download sekmesi altından Add butonu yardımı ile STM32F4xx Flash 1M seçimi yapılır (Şekil 5.9). Şekil 5.9 Proje dosyası oluşturma ve gerekli debugger ayarları yapıldıktan sonra sıra kod yazma işlemine ve yazılan kodu derleyip kite yüklemeye geldi. Kodlarımızı, oluşturduğumuz.c uzantılı sayfaya yazacağız.
Led Açma Kapatma Uygulaması Öncelikle projede kullanacağımız kütüphaneleri eklememiz gerekmektedir. Project- Manage-Run time environment yolları takip edilerek açılan pencereden projemize, kullanacağımız kütüphaneleri ekleriz. Açılan pencereden sırasıyla Device-STM32 Cube Hal seçeneklerine tıklanır. Bu kısımda eklenebilecek kütüphaneler yer almaktadır. Biz led yakıp söndürme uygulaması için *GPIO, RCC kütüphanelerini kullanacağız. Ancak alt kısımda uyarı mesajı çıkacaktır. Eğer Resolve butonuna tıklarsanız ilgili diğer kütüphaneler otomatik seçilecek ve mesaj kaybolacaktır. Bu işlemi Resolve butonuna basmadan STM32 Cube Framework seçeneğinden Class kütüphanesini ve STM32 Cube Hal seçeneği altından COMMON ve CORTEX kütüphanelerini seçerek de yapabilirsiniz (Şekil 5.10). *GPIO ( general purpose input output ): Genel amaçlı giriş çıkış pini olarak Türkçeye çevrilebilir. Bu pinler programlayıcılar tarafından kontrol edilip yönlendirilirler. Şekil 5.10 OK butonuna basıldıktan sonra seçilen kütüphanelerin proje dosyası içerisinde Device başlığı altında olduğunu göreceksiniz. Bu işlemden sonra, kütüphane dosyalarının yolunu Keil programında tanımlamamız gerekecek. Bu işlemi Project Options for Target seçenekleri ile açılan pencereden C/C++ sekmesi altından Include Paths kısmına
bilgisayarımıza indirdiğimiz Libraries\STM32F4xx_StdPeriph_Driver\inc yolunu girerek yaparız (Şekil 5.11). Standart kütüphaneleri STM32F4 Discovery için buradan indirebilirsiniz. Geriye son bir işlem kalmaktadır. Bu da C/C++ sekmesi altındaki Define kısmına şu tanımlamaların yapılmasıdır: HSE_VALUE=8000000,USE_STDPERIPH_DRIVER Şekil 5.11 Bu kısıma kadar yaptığımız tüm işlemleri, yapacağımız bütün projelerde uygulayacağız. Bu yüzden bu kısımların iyi anlaşılması önemlidir. Şimdi kodumuzu yazmaya başlayalım. Kodlarımızı oluşturduğumuz.c dosyasına yazacağız.
// kütüphaneler projeye eklenir #include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" // STM32F4 üzerindeki ledlerin pin tanımlamaları yapılır #define yesil_led 12 #define turuncu_led 13 #define kirmizi_led 14 #define mavi_led 15 int main() { int sayac; int pin = yesil_led; // yeşil led seçildi // GPIO tanımlamaları yapılır uint32_t mode = GPIO_Mode_OUT << (pin * 2); // GPIO çıkış modu uint32_t speed = GPIO_Speed_100MHz << (pin * 2); uint32_t type = GPIO_OType_PP << pin; uint32_t pullup = GPIO_PuPd_NOPULL << (pin * 2); // peripheral clock başlatıldı RCC->AHB1ENR = RCC_AHB1Periph_GPIOD; GPIOD->MODER = mode; GPIOD->OSPEEDR = speed; GPIOD->OTYPER = type; GPIOD->PUPDR = pullup; // ledin yakılıp söndürülme (toggle) işlemi bu döngü içerinde // yapılır while (1) { GPIOD->BSRRL = (1 << pin); for (sayac = 0; sayac < 500000; sayac++); GPIOD->BSRRH = (1 << pin); for (sayac = 0; sayac< 500000; sayac++); } } Kod kutusundaki kodların yanlarında açıklama satırları mevcut. Ancak bazı kodların ne iş yaptığını açıklayalım. uint32_t mode = GPIO_Mode_OUT << (pin * 2); kodu ile GPIO modunu ayarlarız. Aslında bu kodu GPIOD->MODER = mode; bununla birlikte açıklamak daha iyi olacaktır. Bu kodlar ile D portunun ilgili pini çıkış olarak ayarlanır. pin*2 ile yeşil led için 24 elde edilir. Yani 24 bit sola shift edilmesi anlamına gelmektedir. bu işaret de OR kapısı ile maskelemek anlamına gelmektedir. Shifting işlemini detaylıca anlatmak gerekirse;
32 bitte karşılığı : 0000 0001 0000 0000 0000 0000 0000 0000 8 bit ile karşılığı : 0100 0000 dır. Bu adresler ile ilgili pin bu komutlar kullanılarak çıkış olarak ayarlanmıştır. uint32_t speed = GPIO_Speed_100MHz << (pin * 2); ve kodları ile ilgili pinin çalışma hızı 100MHz olarak ayarlanır. GPIOD->OSPEEDR = speed; uint32_t type = GPIO_OType_PP << pin; ve olarak ayarlanan pin çıkışı push pull (0) olarak ayrlanır. GPIOD->OTYPER = type; kodları ile çıkış uint32_t pullup = GPIO_PuPd_NOPULL << (pin * 2); ve GPIOD->PUPDR = pullup; kodları ile ledin pull up direncinin olduğu programa tanıtılmıştır. GPIOD->BSRRL = (1 << pin); kodu ile pin numarası sola shift edilerek set edilmiştir. Yani lojik 1 verilmiştir. GPIOD->BSRRH = (1 << pin); kodu ile pin numarası sola shift edilerek reset edilmiştir. Yani lojik 0 verilmiştir. for (sayac = 0; index < 500000; sayac++); kodu ile gecikme verilmiştir. Yani led bu kodun çalışma süresi kadar açık yada kapalı kalmıştır. Kodumuzun anlaşıldığını düşünüyorum. Şimdi bu kodu derleyip kitimizde koşturabiliriz. Bu kısımların nasıl yapıldığını yukarıda anlatmıştım. Bu işlemi yaptıktan sonra yeşil ledin yanıp söndüğünü göreceksiniz. İlk uygulamamız hayırlı olsun. Butonla Led Kontrol Uygulaması STM32F4 Discovery kiti üzerinde kullanıcılar için tanımlanmış bir buton bulunmaktadır. Bu uygulamada kullanıcılar için tanımlanmış bu butona basarak, kit üzerinde bulunan 4 adet ledin yakılıp söndürülmesi yapılmıştır. Butona ilk basıldığında turuncu ve sarı ledler yanaca, tekrar basıldığında sadece mavi ve kırmızı ledler yanacaktır. Bu kodu, bu alanlarda profesyonel diyebileceğim ve kendisinden birçok konuda yardım aldığım Tuna Ayan abimin paylaşımından aldım. Kendisine teşekkürü bir borç bilirim.
// kutuphaneler koda eklendi #include "stm32f4xx.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" int main() { volatile int toggle=0; // değişkenler tanimlandi volatile int control=0; RCC->AHB1ENR = 0x00000009; //PortA ve PortD üzerindeki clock açilir. // 0x55000000 kismi kod kutusu altinda detayli bir sekilde anlatilmistir GPIOD->MODER = 0x55000000; //PortD üzerindeki 15,14,13,12 pinler çikis olarak tanimlanir. //MODER reg içerisindeki "00" degeri input olarak kabul edildiginden PORTA için bir degisiklik //yapmayacagiz. GPIOD->OSPEEDR= 0xFFFFFFFF;//Düsük akimda çalisma gibi bir sinirimiz su an yok. O yüzden max //output hizinda çalisiyoruz. while(1) { // IDR: input data register. Giri_ olarak ayarlanan pini okur if(gpioa->idr & 0x000000001)//butona basildi mi { control=1; //ilk basista ledler yanmaya baslayacak while(gpioa->idr & 0x00000001) continue; //butondan elimizi çekene kadar bekle toggle=~toggle; } } } if(control) { if (toggle) // ODR: output data register. Çikis olarak ayarlanan pine istenilen cikis sinyalini gonderir GPIOD->ODR= 0x00003000;// turuncu ve sari ledler yansin else GPIOD->ODR= 0x0000C000;// Mavi kirmizi ledler yansin } Kod ile ilgili herşeyin anlaşılır olduğunu düşünüyorum. Bazı kısımları açıklama satırları ile anlatmaya çalıştım. Ancak tek bir noktaya değinmek istiyorum. Çünkü bununla ilgili forumlarda çok fazla soruyla karşılaştım. GPIOD->MODER = 0x55000000; Bu kodun nasıl 15,14,13,12. pinleri çıkış olarak ayarladığını anlatmak istiyorum. Bu koddaki 0x sayının hexadecimal olduğunu gösterir. Diğer kısımlar alttaki resimde detaylıca anlatılmıştır (Şekil 5.12).
Şekil 5.12 Kaynaklar [1] http://www.arm.com/products/processors/classic/arm7/index.php [2] http://www.cncdesigner.com/stm/baglanti.jpg http://www.mcu-turkey.com/stm32f4-discovery-ilk-incelemeler/ http://carus.aces.shu.ac.uk/staff/engafh/stm32/gpio_stm32_stmf4discovery.pdf http://www.st.com/st-webui/static/active/en/resource/technical/document/user_manual/dm00039084.pdf YAZAN: GÖKHAN GÖL Web adresi : http://www.gokhangol.com/ E-mail : golmuhendis@gmail.com