Arduino ile HX1230 Port Manipülasyonu Destekli Hız Aşırtma

👤 Yazar: ozcan 📅 Tarih: 13.07.2026 06:39 👁️ Görüntüleme: 32

İleri Seviye : Port Manipülasyonu (Hız Aşırtma)

Arduino'nun standart digitalWrite() fonksiyonu pin durumunu değiştirmek için arka planda yaklaşık 40-50 işlemci çevrimi (cycle) harcar. Ekranı ters çevirip doğrudan D0-D7 pinlerine oturtmamızın bize sağladığı en büyük avantaj, bu pinlerin tamamının ATmega328P işlemcisinin donanımsal PORTD yazmacına (register) bağlı olmasıdır. İşlemciye doğrudan port seviyesinde emir vererek, ekran yenileme ve veri transfer hızını 10 kattan fazla artırabilir ve işlemci yükünü neredeyse sıfıra indirebiliriz.

Önemli Grafik Notu: Port manipülasyonu doğrudan işlemci mimarisine müdahale ettiği için D0 ve D1 pinlerini kullanan USB-Seri haberleşme hattını etkiler. Kodu Arduino'ya yüklerken ekranın takılı olmaması veya yüklendikten sonra Arduino'nun harici bir kaynaktan beslenmesi önerilir.

Port Manipülasyonu Destekli Hız Aşırtmalı Kod Bloğu

Aşağıdaki kod, hx1230_byteYaz fonksiyonu içindeki tüm yavaş pin komutlarını tek satırlık bit maskeleme işlemlerine dönüştürür. Zamanlama (Clock) sinyali işlemci hız sınırında üretilir:

// HX1230 PORTD Donanımsal Bit Karşılıkları (D0-D7 Arası)
// Pinlerin PORTD üzerindeki bit pozisyonları:
// D0=Bit0 (RESET), D1=Bit1 (CE), D2=Bit2 (NC), D3=Bit3 (DIN)
// D4=Bit4 (CLK),   D5=Bit5 (VCC), D6=Bit6 (BL), D7=Bit7 (GND)

#define BIT_RESET  0 // PORTD0
#define BIT_CE     1 // PORTD1
#define BIT_DIN    3 // PORTD3
#define BIT_CLK    4 // PORTD4

// Süper Hızlı 9-Bit Port Manipülasyonu İletişim Fonksiyonu
void hx1230_byteYaz(uint8_t veri, uint8_t is_veri) {
  // 1. Çip Seçimini Aktif Et (CE -> LOW)
  PORTD &= ~(1 << BIT_CE);
  
  // 2. İlk Bit: D/C (0: Komut, 1: Veri)
  PORTD &= ~(1 << BIT_CLK); // CLK -> LOW
  if (is_veri) {
    PORTD |= (1 << BIT_DIN); // DIN -> HIGH
  } else {
    PORTD &= ~(1 << BIT_DIN); // DIN -> LOW
  }
  PORTD |= (1 << BIT_CLK);  // CLK -> HIGH (Veri kilitlendi)
  
  // 3. Geri kalan 8 bitlik veri bloğunu döngüyle uçuruyoruz
  for (int i = 7; i >= 0; i--) {
    PORTD &= ~(1 << BIT_CLK); // CLK -> LOW
    
    if ((veri >> i) & 0x01) {
      PORTD |= (1 << BIT_DIN);  // DIN -> HIGH
    } else {
      PORTD &= ~(1 << BIT_DIN); // DIN -> LOW
    }
    
    PORTD |= (1 << BIT_CLK);  // CLK -> HIGH (Veri kilitlendi)
  }
  
  // 4. İşlem Bitti, Çip Seçimini Kapat (CE -> HIGH)
  PORTD |= (1 << BIT_CE);
}

// Komut ve Veri sarmalayıcıları aynı kalıyor
void hx1230_komutYaz(uint8_t komut) { hx1230_byteYaz(komut, LOW); }
void hx1230_veriYaz(uint8_t veri)   { hx1230_byteYaz(veri, HIGH); }

// Orijinal Kararlı Başlatma Protokolü
void hx1230_init() {
  // Donanımsal Reset (Port Seviyesinde)
  PORTD &= ~(1 << BIT_RESET); // RESET -> LOW
  delay(5);
  PORTD |= (1 << BIT_RESET);  // RESET -> HIGH
  delay(5);
  
  hx1230_komutYaz(0xE2); // Software Reset
  delay(2);
  hx1230_komutYaz(0x2F); // Power Control ON
  hx1230_komutYaz(0xA4); // Normal RAM Modu
  hx1230_komutYaz(0xA6); // Normal Renk Modu
  hx1230_komutYaz(0xA0); // Sütun yönü
  hx1230_komutYaz(0xC0); // Satır yönü 
  hx1230_komutYaz(0x40); 
  hx1230_komutYaz(0x8B); // Orijinal Kontrast Sabiti (0x8B)
  hx1230_komutYaz(0xAF); // Display ON
  delay(10);
}

// 5x7 Standart ASCII Font Tablosu (Harfler, Rakamlar ve Temel Semboller)
const uint8_t PROGMEM font_haritasi[][5] = {
  {0x00, 0x00, 0x00, 0x00, 0x00}, // Boşluk
  {0x00, 0x00, 0x5f, 0x00, 0x00}, // !
  {0x00, 0x07, 0x00, 0x07, 0x00}, // "
  {0x14, 0x7f, 0x14, 0x7f, 0x14}, // #
  {0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $
  {0x23, 0x13, 0x08, 0x64, 0x62}, // %
  {0x36, 0x49, 0x55, 0x22, 0x50}, // &
  {0x00, 0x05, 0x03, 0x00, 0x00}, // '
  {0x00, 0x1c, 0x22, 0x41, 0x00}, // (
  {0x00, 0x41, 0x22, 0x1c, 0x00}, // )
  {0x14, 0x08, 0x3e, 0x08, 0x14}, // *
  {0x08, 0x08, 0x3e, 0x08, 0x08}, // +
  {0x00, 0x50, 0x30, 0x00, 0x00}, // ,
  {0x08, 0x08, 0x08, 0x08, 0x08}, // -
  {0x00, 0x60, 0x60, 0x00, 0x00}, // .
  {0x20, 0x10, 0x08, 0x04, 0x02}, // /
  {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0
  {0x00, 0x42, 0x7f, 0x40, 0x00}, // 1
  {0x42, 0x61, 0x51, 0x49, 0x46}, // 2
  {0x21, 0x41, 0x45, 0x4b, 0x31}, // 3
  {0x18, 0x14, 0x12, 0x7f, 0x10}, // 4
  {0x27, 0x45, 0x45, 0x45, 0x39}, // 5
  {0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6
  {0x01, 0x71, 0x09, 0x05, 0x03}, // 7
  {0x36, 0x49, 0x49, 0x49, 0x36}, // 8
  {0x06, 0x49, 0x49, 0x29, 0x1e}, // 9
  {0x00, 0x36, 0x36, 0x00, 0x00}, // :
  {0x00, 0x56, 0x36, 0x00, 0x00}, // ;
  {0x08, 0x14, 0x22, 0x41, 0x00}, // <
  {0x14, 0x14, 0x14, 0x14, 0x14}, // =
  {0x00, 0x41, 0x22, 0x14, 0x08}, // >
  {0x02, 0x01, 0x51, 0x09, 0x06}, // ?
  {0x32, 0x49, 0x79, 0x41, 0x3e}, // @
  {0x7e, 0x11, 0x11, 0x11, 0x7e}, // A
  {0x7f, 0x49, 0x49, 0x49, 0x36}, // B
  {0x3e, 0x41, 0x41, 0x41, 0x22}, // C
  {0x7f, 0x41, 0x41, 0x22, 0x1c}, // D
  {0x7f, 0x49, 0x49, 0x49, 0x41}, // E
  {0x7f, 0x09, 0x09, 0x09, 0x01}, // F
  {0x3e, 0x41, 0x49, 0x49, 0x7a}, // G
  {0x7f, 0x08, 0x08, 0x08, 0x7f}, // H
  {0x00, 0x41, 0x7f, 0x41, 0x00}, // I
  {0x20, 0x40, 0x41, 0x3f, 0x01}, // J
  {0x7f, 0x08, 0x14, 0x22, 0x41}, // K
  {0x7f, 0x40, 0x40, 0x40, 0x40}, // L
  {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M
  {0x7f, 0x04, 0x08, 0x10, 0x7f}, // N
  {0x3e, 0x41, 0x41, 0x41, 0x3e}, // O
  {0x7f, 0x09, 0x09, 0x09, 0x06}, // P
  {0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q
  {0x7f, 0x09, 0x19, 0x29, 0x46}, // R
  {0x46, 0x49, 0x49, 0x49, 0x31}, // S
  {0x01, 0x01, 0x7f, 0x01, 0x01}, // T
  {0x3f, 0x40, 0x40, 0x40, 0x3f}, // U
  {0x1f, 0x20, 0x40, 0x20, 0x1f}, // V
  {0x3f, 0x40, 0x38, 0x40, 0x3f}, // W
  {0x63, 0x14, 0x08, 0x14, 0x63}, // X
  {0x07, 0x08, 0x70, 0x08, 0x07}, // Y
  {0x61, 0x51, 0x49, 0x45, 0x43}  // Z
};


void hx1230_ekranTemizle() {
  for (int sayfa = 0; sayfa < 9; sayfa++) {
    hx1230_komutYaz(0xB0 + sayfa);
    hx1230_komutYaz(0x00);
    hx1230_komutYaz(0x10);
    for (int sutun = 0; sutun < 96; sutun++) { hx1230_veriYaz(0x00); }
  }
}

void hx1230_yaziYaz(int satir, int sutun, const char* metin) {
  hx1230_komutYaz(0xB0 + satir);
  hx1230_komutYaz(sutun & 0x0F);
  hx1230_komutYaz(0x10 | ((sutun >> 4) & 0x0F));
  while (*metin) {
    char karakter = *metin;
    if (karakter >= 'a' && karakter <= 'z') karakter -= 32;
    int idx = karakter - 32;
    if (idx >= 0 && idx < 95) {
      for (int i = 0; i < 5; i++) {
        hx1230_veriYaz(pgm_read_byte(&(font_haritasi[idx][i])));
      }
      hx1230_veriYaz(0x00);
    }
    metin++;
  }
}

void setup() {
  // DDRD (Data Direction Register D) ile D0-D7 pinlerinin hepsini TEK SEFERDE çıkış yapıyoruz.
  // B11111111 ifadesi tüm pinlerin OUTPUT olduğunu gösterir.
  DDRD = B11111111; 

  // Ekran Güç Düzenlemesi (VCC ve Arka Işık HIGH, GND ve NC LOW)
  // PORTD üzerinde bit 5 (VCC) ve bit 6 (BL) aktif ediliyor, diğer veri hatları başlangıç durumuna alınıyor.
  PORTD = B01110010; 
  delay(100);
  
  hx1230_init();         
  hx1230_ekranTemizle(); 
  
  hx1230_yaziYaz(1, 10, "PORT MANIPULASYONU");
  hx1230_yaziYaz(3, 22, "HIZ ASIRTMA");
  hx1230_yaziYaz(5, 30, "10X FAST!");
}

void loop() {
  // Boş döngü
}

Kodun Çalışma Mantığı ve Matematiksel Altyapısı

  • DDRD = B11111111; Normalde tek tek 8 tane pinMode(pin, OUTPUT); yazmamız gerekirken, bu komutla işlemcinin D Portundaki tüm pinleri (D0-D7) tek bir işlemci çevriminde çıkış moduna alıyoruz.
  • PORTD |= (1 << BIT_CLK); Bit kaydırma (Shift) ve VEYA eşitleme operatörüdür. İlgili pini (örneğin CLK pinini) diğer pinlerin durumunu bozmadan mikrosaniyeler içinde HIGH seviyesine çeker.
  • PORTD &= ~(1 << BIT_CLK); Bit tersleme (NOT) ve VE eşitleme operatörüdür. Diğer pinlere hiç dokunmadan sadece CLK pinini sıfıra, yani LOW seviyesine indirir.

💬 Yorumlar

Henüz yorum yapılmamış. İlk yorumu siz yapın!

Bir Yorum Bırakın

Güvenlik Kontrolü:

Yenidir.com
↑ Sayfa Başı
📞 İletişim ✉ E-Posta Gönder 🟥 YouTube
© 2026 Yenidir.com
Yenidir CMS V0.1