← Tüm makaleler

GPIO Programlama

Dijital giriş ve çıkış

GPIO Programlaması

Bir GPIO pini, CPU'nun fiziksel dünyayla konuştuğu tek noktadır. Bir bit register'a yazarak bir transistörü açarsınız — o transistör 20 mA akım çeker, LED yanar. Aynı bit giriş olarak yapılandırıldığında bir butona bağlı voltaj seviyesini okur. Her GPIO işleminde yanıtlamanız gereken üç soru vardır: Yön (giriş mi, çıkış mı?), seviye (HIGH mi, LOW mu, pull-up mı?) ve reset durumu (açılışta pinin durumu ne olacak?).

Bu dersin sonunda şunları yapabileceksiniz: AVR'de DDRx/PORTx/PINx register'larını kullanarak GPIO'yu yapılandırmak ve okumak; STM32'de MODER/ODR/IDR register'larıyla aynı işlemleri yapmak; buton debounce mantığı uygulamak.

ATmega328P Port Kaydedicileri

Her port için 3 kaydedici vardır:

Kaydedici Görevi
DDRx Pin yönü: 1 = çıkış, 0 = giriş
PORTx Çıkış değeri veya pull-up kontrolü
PINx Giriş değerini okuma (salt okunur)

{diagram:gpio-pin-states}

{diagram:gpio-control}

Dijital Çıkış — LED Kontrolü

#include <avr/io.h>
#include <util/delay.h>

int main(void) {
    // PB5 pinini çıkış yap
    DDRB |= (1 << DDB5);

    while(1) {
        PORTB |= (1 << PORTB5);   // LED aç
        _delay_ms(500);
        PORTB &= ~(1 << PORTB5);  // LED kapat
        _delay_ms(500);
    }
}

Dijital Giriş — Buton Okuma

#include <avr/io.h>

int main(void) {
    DDRB &= ~(1 << DDB0);    // PB0 giriş
    PORTB |= (1 << PORTB0);  // Pull-up direnci aktif
    DDRB |= (1 << DDB5);     // PB5 çıkış (LED)

    while(1) {
        // Buton basılı mı? (aktif low — basınca GND'ye çeker)
        if (!(PINB & (1 << PINB0))) {
            PORTB |= (1 << PORTB5);   // LED aç
        } else {
            PORTB &= ~(1 << PORTB5);  // LED kapat
        }
    }
}

İpucu: PORTB |= (1 << PORTB0) ile bir giriş pininde dahili pull-up direncini etkinleştirirsiniz. Bu sayede harici direnç kullanmanıza gerek kalmaz.

Buton Debounce

Mekanik butonlar basıldığında birkaç milisaniye boyunca titreşir (bounce). Bu durumu yazılımla çözmek gerekir:

#include <avr/io.h>
#include <util/delay.h>

uint8_t button_read(void) {
    if (!(PINB & (1 << PINB0))) {  // Basılı mı?
        _delay_ms(20);              // 20ms bekle
        if (!(PINB & (1 << PINB0))) {  // Hâlâ basılı?
            return 1;
        }
    }
    return 0;
}

int main(void) {
    DDRB &= ~(1 << DDB0);
    PORTB |= (1 << PORTB0);  // Pull-up
    DDRB |= (1 << DDB5);     // LED çıkış

    uint8_t led_state = 0;

    while(1) {
        if (button_read()) {
            led_state ^= 1;                      // Toggle
            PORTB ^= (1 << PORTB5);
            while (!(PINB & (1 << PINB0)));      // Bırakılana kadar bekle
        }
    }
}

STM32 GPIO — Register Seviyesinde

STM32'de bir GPIO pinini kullanmadan önce üç adım gerekir: clock aç, mod ayarla, yaz/oku.

#include "stm32f4xx.h"

void GPIO_Init(void) {
    // Adım 1 — Saat kaynaklarını aç (clock açılmadan register yazma etkisizdir)
    RCC->AHB1ENR |= (1 << 0);   // GPIOA clock etkinleştir
    RCC->AHB1ENR |= (1 << 2);   // GPIOC clock etkinleştir

    // Adım 2 — PA5: çıkış modu (MODER bitler 11:10 = 01)
    GPIOA->MODER &= ~(0x3 << 10);  // önce temizle
    GPIOA->MODER |=  (0x1 << 10);  // 01 = genel amaçlı çıkış

    // Adım 3 — PC13: giriş modu (MODER bitler 27:26 = 00, varsayılan)
    GPIOC->MODER &= ~(0x3 << 26);  // 00 = giriş modu

    // Dahili pull-up etkinleştir: PC13 (PUPDR bitler 27:26 = 01)
    GPIOC->PUPDR &= ~(0x3 << 26);
    GPIOC->PUPDR |=  (0x1 << 26);  // 01 = pull-up
}

int main(void) {
    GPIO_Init();

    while (1) {
        if (!(GPIOC->IDR & (1 << 13))) {   // buton basılı mı? (aktif low)
            GPIOA->ODR |=  (1 << 5);        // PA5 HIGH — LED aç
        } else {
            GPIOA->ODR &= ~(1 << 5);        // PA5 LOW — LED kapat
        }
    }
}
Register Görevi
MODER Pin yönü: 00=giriş, 01=çıkış, 10=AF, 11=analog
ODR Çıkış veri registerı — bit yazarak pin HIGH/LOW yapılır
IDR Giriş veri registerı — salt okunur, pinin anlık durumunu verir
PUPDR Pull-up/down: 00=yok, 01=pull-up, 10=pull-down
Kurslara göz at →