MSP430 ile 2×16 Karakter LCD Uygulaması

Elektronik devrelerde, bazen kullanıcıyı bilgilendirmek, onunla bağlantı kurmak gerekebilir. Bunun çeşitli yolları mevcut. Örneğin kullanıcıya sadece sıcaklık, saat gibi sayısal bilgiler verilecekse 7 segment displayler yeterli olacaktır. Kullanıcıya yazılı bir bilgi verilecekse 16 segment displayler, karakter LCD veya grafik LCD’ler kullanılabilir. Daha karmaşık devrelerde ise devreyi bilgisayarla haberleştirip, gözlemleri ve kontrolü bilgisayar yazılımı üzerinden yapmak mantıklı bir çözüm olabilir. Bu yazımda, piyasada sıklıkla bulunan HD44780 sürücülü karakter LCD’leri nasıl kullanabileceğimizden bahsetmeye çalışacağım.Öncelikle kurduğum devrenin şemasını verip, LCD’nin pinlerinden bahsetmeye çalışayım.

Devre şeması

Devre şeması

VSS (1) : LCD’nin toprak bağlantısı.
VDD (2) : LCD’nin besleme bacağı. Buraya 5V uygulanmalı.
VEE (3) : Buraya uygulanan gerilime göre LCD’nin kontrastı değişmekte. Bir potansiyometre ile gerilimi değiştirerek LCD’deki karakterlerin daha rahat görülmesi sağlanabilir.
RS (4) : LCD’ye göndereceğimiz bilgiler, LCD’yi yönetmemiz için komutlar (“0”), ya da ekranda yazacak karakterler (“1”) olabilir. Bu pin bunu belirlememizi sağlıyor.
R/W (5) : HD44780 uyumlu LCD’lere veri gönderebilir, ya da LCD’den veri alabiliriz. Biz şu an sadece LCD’ye veri göndereceğimiz için bu ucu toprağa çektim.
E (6) : MSP’nin portuna bastığımız bitlerin LCD’ye gönderilmesi için, E pinine düşen kenar uygulanmalıdır.
D0 (7) – D7 (14) : LCD’nin giriş uçları. LCD’ye göndereceğimiz bir komutla, giriş için 8 pin ya da 4 pin kullanabiliyoruz. Böylece ek bir uğraş vermeden LCD’yi toplamda 6 pin kullanarak sürebiliyoruz.
BL+ (15) – BL- (16) : Her ne kadar şemada gözükmese de iki pin daha mevcut. Bu pinler de LCD’nin arka aydınlatması için kullanılıyor. Bu iki pin arasına 5 voltluk bir gerilim uygularsak LCD’nin aydınlatması çalışacak ve yazıları görebileceğiz.

Kodları direkt projenin main.c dosyasına yazmaktansa, çoğu kişinin yaptığı gibi bu uygulamada ve daha sonra LCD ile yapacağım uygulamalarda kullanmak için, LCD ile haberleşmede kullanacağım fonksiyonları içeren bir kütüphane dosyası yazmak istedim. Fonksiyon fonksiyon anlatarak ilerlemeye başlayalım. İlk önce RS ve E’ye bağlı pinleri daha kolay değiştirebilmek için şu tanımlamaları yaptım:

#define    RS P2OUT_bit.P2OUT_6   // LCD'nin RS pini MCU'nun P2.6 pinine bağlandı.
#define    E  P2OUT_bit.P2OUT_7   // LCD'nin E pini MCU'nun P2.7 pinine bağlandı.

Bazı yerlerde ufak beklemeler koymak faydalı olabilir. Bunun için “lcdBekle” isimli şu basit fonksiyonu kullanıyorum. “ms” adıyla integer bir parametre alıyor, gelen değere bağlı olarak bir bekleme yapıyor. Her ne kadar emin olmasam da yaklaşık olarak gelen değer kadar milisaniye beklediğini düşünüyorum. Fonksiyon şu:

void lcdBekle(int ms)             // Bekleme fonksiyonu
{
  unsigned int i, j;
  i = ms;
  for(j = 0 ; j < 250 ; j++)
  {
     for( ; i > 0 ; i--);
     i = ms;
  }
}

LCD’ye verilerin aktarılabilmesi için E pinine düşen kenar uygulanması gerektiğinden bahsetmiştim. Bu fonksiyon da bu işi yapıyor. E pinini önce “1”, sonra da “0” seviyesine çekerek düşen kenar uygulanmış oluyor. “lcdEDegistir” fonksiyonu:

void lcdEDegistir(void)           // E pini düşen kenar tetiklemeli.
{                                 // Bu yüzden gönderdiğimiz bilginin LCD üzerinde
  E = 1;                          // işlem görmesi için E ucuna düşen kenar uyguluyoruz.
  E = 0;                          // Bunu da E'yi önce "1", sonra "0" yaparak hallediyoruz.
}

LCD’ye gönderdiğimizi bilgilerin komut ya da veri olabileceğini, ve buna bağlı olarak RS pinine “1” ya da “0” uygulamamız gerektiğini söylemiştim. Bunu yapması için de “lcdNeYazilacak” isimli fonksiyonu kullanıyorum. char tipinde bir değişken alıyor, ve bu değişken eğer “k” ise, yani komut gönderilecekse RS pinini “0”, “v”, yani veri gidecekse RS pinini “1” yapıyor.

void lcdNeYazilacak(char ne)      // LCD'ye giden bilgimiz veri ya da komut olabilir.
{
  if(ne == 'k')                   // Komut ise;
    RS = 0;                       // RS pini "0" yapılır.
  else if(ne == 'v')              // Veri ise;
    RS = 1;                       // RS pini "1" yapılır.
}

Şimdi de LCD’ye bilgi gönderdiğimiz “lcdGonder” isimli fonksiyona gelelim. Fonksiyon iki parametre alıyor, biri gönderilen bilginin komut mu, veri mi olduğunu belirttiğimiz char tipindeki değişken, diğeri de gidecek bilginin olduğu integer tipindeki değişken. Devrede veri iletimi için 4 pini kullanacağımız için bilgiyi iki parçaya bölerek göndereceğiz. Önce değerlikli dört biti, sonra değerliksiz dört biti göndereceğiz. Fonksiyonun yaptığı iş kabaca şu: bilgi porta basılıyor, gidecek bilginin türüne göre RS pini ayarlanıyor (lcdNeYazilacak fonksiyonuyla), daha sonra E pinine düşen kenar uygulanıyor (lcdEDegistir fonksiyonuyla). Daha sonra bilgi dört bit sola kaydırılarak değerliksiz bitler için de aynı işlem uygulanıyor.

void lcdGonder(char ne, int veri) // Gidecek bilginin türünü ve bilgiyi aldık.
{
  P1OUT = veri;                   // Bilgiyi P1OUT'a bastık. Böylece LCD ile bağlantılı kısım en değerlikli dört bit oluyor.
  lcdNeYazilacak(ne);             // Fonksiyona gelen bilgi türünü diğer fonksiyona aktarıp RS pinini ayarladık.
  lcdEDegistir();                 // Bilginin aktif olması için E pinine düşen kenar uyguladık.

  veri = (veri << 4);             // Şimdi değerliksiz dört biti göndereceğiz. Veriyi dört bit sola kaydırdık.
                                  // Bu şekilde verinin değerliksiz bitleri, artık değerlikli kısımda.
  P1OUT = veri;                   // Değişen veriyi P1OUT'a bastık.
  lcdNeYazilacak(ne);             // RS pinini ayarladık.
  lcdEDegistir();                 // E pinine düşen kenar uyguladık.
}

LCD’yi kullanabilmek için ilk olarak ne şekilde kullanmak istiyorsak ona uygun olan komutları LCD’ye göndermeliyiz. Bu komutlar için LCD’nin datasheetini incelediğimizde (sayfa 24-25) şöyle bir tablo karşımıza çıkıyor:

Komut tablosu

Şimdi bu tablodan yararlanarak “lcdHazirla” isimli fonksiyonumuzu yazalım:

void lcdHazirla(void)
{
  lcdBekle(15);                   // Bir süre beklendi.
  lcdGonder('k', 0x02);           // "00000010" yani imleç en başa gidecek.
  lcdGonder('k', 0x28);           // "00101000" yani 4 pin, 2 satır, 5x7 karakter kullanılacak.
  lcdGonder('k', 0x0C);           // "00001000" yani imleç gizlenecek.
  lcdGonder('k', 0x06);           // "00000110" yani imleç yazılan her karakterden sonra sağa doğru kayacak.
  lcdGonder('k', 0x01);           // "00000001" yani LCD temizlenecek.
  lcdBekle(10);                   // Bir süre beklendi.
}

LCD’de gözükecek yazıları istediğimiz yerde göstermek isteriz. Örneğin daha hoş bir görüntü için kısa yazıları ortalayabiliriz. Ya da bir alt satırda yazının gözükmesini isteyebiliriz. Bunun için yazıyı yazmaya hangi satır ve sütundan başlanacağını ayarlamamızı sağlayan komutlar göndermeliyiz. Bunun için üstteki komut tablosundan “Set DDRAM address” satırındaki bilgileri kullanacağız. Tabloya göre, göndereceğimiz komutun 7. biti “1” olacak. DDRAM adresleri için yine datasheete baktığımızda (sayfa 12) şöyle bir tablo var:

DDRAM adres tablosu

Göndereceğimiz komutta 7. bit “1” olacağından, göndermemiz gereken komutlar, 1. satır için : 80 – 8F, ikinci satır için ise C0 – CF arasında olmalı. Buna uygun olarak fonksiyonumuzu yazalım:

void lcdHucreyeGit(unsigned int satir, unsigned int sutun)
{
  if(satir == 1)
  {
    sutun--;                      // 1-16 arasında giriş için 0-15 arası değer gelecek.
    lcdGonder('k', 0x80 + sutun); // Komut tablosuna göre 80-8F arasında değer gönderiliyor.
  }

  else if(satir == 2)
  {
    sutun--;                      // 0-15 arasında bir değer elde etmek için.
    lcdGonder('k', 0xC0 + sutun); // C0 - CF arası değer gönderiliyor.
  }
}

Şimdi LCD’ye yazdırmak istediğimiz metni gönderdiğimiz fonksiyonu yazalım. Parametre olarak bir karakter dizisi alıyor ve dizinin sonuna gelene kadar harfleri “lcdGonder” fonksiyonuna “v” tipiyle gönderiyor. Böylece metnimiz LCD’ye gönderilmiş oluyor. Fonksiyon şu:

void lcdYaziYaz (char* yazi)      // Bir string bastırmak için fonksiyon.
{
  lcdBekle(1);                    // Bir süre beklendi.
  int i = 0;
  while(yazi[i])                  // Yazının sonuna gelene kadar,
  lcdGonder('v', yazi[i++]);      // Veriyi gönder ve bir sonraki veriye geç.
}

Şimdiki fonksiyonumuz da tek bir harf, bundan daha ziyade integer tipindeki değişkenleri bastırabilmek için. LCD’ye karakterleri, daha doğrusu bunların ASCII kodlarını gönderiyoruz. Sıcaklık bilgisi gibi değeri bir integer değişkende tutulan, değişebilecek bilgileri bastırmak için, bu değişkenleri rakamlarına ayırarak, bu rakamlara 0’ın ASCII kodu olan 0x30’u ekleyerek bu fonksiyona gönderdiğimizde o rakamı LCD’ye karakter olarak göndermiş olacağız.

void lcdHarfYaz (char harf)       // Tek harf bastırmak için fonksiyon.
{
  lcdBekle(1);                    // Bir süre beklendi.
  lcdGonder('v', harf);           // Veriyi gönder.
}

Son fonksiyonumuz da LCD’yi temizlemeye yarayan fonksiyonumuz. Yaptığı iş ise gerekli komutu göndererek LCD’yi temizliyor ve 1. satır 1. sütuna gidiyor. Fonksiyon:

void lcdTemizle(void)
{
  lcdGonder('k', 0x01);           // LCD temizlendi.
  lcdHucreyeGit(1, 1);            // 1. satır, 1. sütuna gidildi.
  lcdBekle(10);                   // Bir süre beklendi.
}

Buraya kadar yazdıklarımız, tüm LCD’li uygulamalarımızda kullanabileceğimiz kütüphane dosyamız. Kütüphane dosyasını ve anlatımda kullandığım diğer dosyaları yazının sonundan indirebilirsiniz. Şimdi bu kütüphaneyi kullanarak LCD’de yazılarımızı gösterelim.

IAR’da yeni bir proje dosyası açalım. Yukarıda yazdığımız fonksiyonları kullanabilmek için kütüphanemizi main.c dosyamıza include etmemiz gerekiyor. Tabii kütüphane dosyasını main.c ile aynı dizine koymamız gerekiyor. Ben kütüphaneme “lcdFonksiyonlar” adın verdiğim için bunu include ediyorum. Siz başka bir isim verdiyseniz o dosyayı include etmelisiniz. Bundan sonra LCD’yi main.c içinde çok basit bir şekilde kullanacağız. main.c’nin kodları ise şöyle:

#include "io430.h"
#include "lcdFonksiyonlar.h"            // LCD için kullanacağımız fonksiyonlar

void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;             // WDT kapatıldı.

  P1DIR = 0xF0;                         // P1.4 - P1.7 arası çıkış yapıldı.
  P2DIR = 0xFF;                         // Port 2 çıkış yapıldı.
  P2SEL = 0x00;                         // Port 2, i/o olarak kullanılacak.

  lcdHazirla();                         // LCD hazırlanıyor.
  lcdBekle(20);                         // Bir süre beklendi.

  lcdHucreyeGit(2, 2);                  // 2. satır, 2. sütuna git.
  lcdYaziYaz("berkbaykal.com");         // "berkbaykal.com" yaz.

  lcdHucreyeGit(1, 2);                  // 1. satır, 2. sütuna git.
  lcdYaziYaz("MSP-LCD Deneme");         // "MSP-LCD Deneme" yaz.

  while(1);                             // Sonsuz döngüde bekle.
}

Gördüğünüz gibi yazdığımız kütüphane sayesinde main.c dosyamız çok sade ve anlaşılabilir oldu. LCD ile yapacağımız her uygulamada bu kütüphaneyi kullanabilir, böylece pratik bir şekilde LCD’de istediğimiz metni gösterebiliriz.

Devrenin Proteus simülasyonundan bir görüntü:

Simülasyon

Bir de gerçek hayattaki çalışmasını görelim:

Devrenin çalışırkenki hali

Son olarak kütüphane, IAR projesi ve proteus dosyalarını verip yazımı bitireyim. Dosyaları rar’dan çıkartıp öyle çalışırsanız, olası hataları engellersiniz. Dosyayı aşağıdaki linkten indirebilirsiniz:

http://www.berkbaykal.com/blog/upload/msp430-lcd.rar

Uzun bir yazı oldu. Elimden geldiğince LCD kullanımını basit bir şekilde anlatmaya çalıştım. Faydalı olması dileğiyle…

Share
  1. MSP430 ve Karakter LCD ile Refleks Ölçer | Berk Baykal - pingback on 30 Mayıs 2011 at 02:38
  2. Cansu Arslan

    Merhaba,sizin yazdığınız kodu üzerinde çalıştığımız CC430F6147 ye uyarladık.
    Ancak yazıyı ekranda göremedik. Pin bağlantılarında data portunun 5 ve 7 inci poetuna 2.5 V gidiyor. Diğer bağlantılara 5 V gidiyor.
    Sorun neyden kanaklanıyor olabilir?

  3. merhaba burada sizin kullandığınız LCD nin adı nedir. Bazı beslemesi 5V olan Lcd ler , msp430 mikroişlemcinin çıkışı 3.5 V ve bunu kabul etmiyor .

  4. Merhaba benim aldığım LCD ATM1602a .LCD yi çalıştıramadım MSP430253 ile. Datasheetinde
    Symbol Min Typ Max Unit
    Supply Voltage for Logic VDD 4.5 5.0 5.5 V
    Supply Voltage for LCD VLCD 4.0 4.5 5.0 V yazıyor .Yani burada bahsedilen LCD nin data uçlarının algılayabildiği Volt seviyelerimi acaba . MSP nin 3.5 V luk verisini kabul etmiyor mu acaba ?

    • Datasheette Vinh – Vinl ile belirtilen değerler lojik 1 ve 0 olarak kabul edeceği voltaj aralıklarını gösterir. Bunları bir kontrol edin derim. Belirttiğiniz değerler besleme voltajları.

Yorum Yap


Not - Bunları KullanabilirsinizHTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>