LaunchPad ile Seri Port Üzerinden LCD Kontrolü

Bu yazımda LaunchPad’in oluşturduğu sanal seri port üzerinden gönderdiğimiz verileri karakter LCD üzerinde nasıl görüntüleyebileceğimizi anlatacağım. Seri port üzerinden gönderdiğimiz verilerin bir kısmını komut olarak kullanacağız. Bu şekilde basit olarak LCD üzerinde bulunduğumuz satırı değiştirebilecek, LCD’yi temizleyebilecek, MSP430 üzerinde tuttuğumuz veriyi ekrana bastırabilecek ve yazıyı kaydırabileceğiz. RS232 haberleşmesi için şu yazımdaki koddan, LCD için ise şu yazımda güncellediğim kütüphaneden faydalanacağız. Bilgisayar tarafında ise bu uygulama için C# ile hazırlamış olduğum bir programı kullanacağız. Bu program sayesinde LCD üzerinde metin, tarih – saat ve RSS beslemesi görüntüleyebilecek, dilersek bunları istediğimiz hızda kaydırabileceğiz.

RS232 ile ilgili olan yazımda, main fonksiyonundaki sonsuz bir döngüde veri gelip gelmediğini kontrol ediyor, geldiyse aynısını geri yolluyorduk. Bu sefer gelen veriye bakacağız, LCD’ye komut olarak belirlediğimiz bir veri geldiyse LCD üzerinde gereken işlemi yapacağız. Gelen veri, bizim komut olarak belirlediklerimizden değilse, veriyi MSP430 tarafında bir dizinin sonuna ilave edeceğiz.

İlk olarak LCD üzerinde hangi işlemleri yapacağımı belirliyorum :

  • Dizide tuttuğum stringi LCD’ye aktarmak.
  • 1. satıra geçmek.
  • 2. satıra geçmek.
  • LCD’deki veriyi bir karakter sola kaydırmak (böylece basit olarak kayan yazı yapacağız).
  • LCD’yi temizlemek.
LCD karakter seti

LCD karakter seti

Şimdi bu komutlarımız için gönderebileceğimiz uygun verileri belirleyelim. Yukarıdaki karakter tablosundan göreceğimiz üzere halihazırda bir karşılığı olan karakterler 33 “!” ile başlıyor. 0 – 7 arası da bizim eklediğimiz Türkçe karakterler. Öyleyse ben komutlarım için 20 – 24 arasını belirledim. Bu durumda komutlarım şöyle oluyor :

  • 20 : MSP430’daki stringi LCD’ye gönder.
  • 21 : 1. satıra git.
  • 22 : 2. satıra git.
  • 23 : Yazıyı bir bit sola kaydır.
  • 24 : Ekranı temizle.

Artık MSP430 tarafında RS232’den aldığım veriyi bir switch – case yapısı ile inceleyerek, komutlardan biri ise komutumu işletebilir, değil ise stringimin sonuna ilave edebilirim. O zaman MSP430 için kodum şu şekilde oluyor :

#include "io430.h"
#include "in430.h"
#include "stdbool.h"
#include "lcdFonksiyonlar.h"

bool rs232Alinacak = 0;      // Veri alınacak mı?
bool rs232Alindi = 0;        // Veri alındı mı?
bool rs232Gonderilecek = 0;  // Veri gönderilecek mi?
int rs232Bit = 0;            // O an kaçıncı bit işlem görüyor?
int rs232Gelen = 0;          // Gelen veri.
int rs232Giden = 0;          // Giden veri.

void rs232Gonder(int);       // Veriyi gönderime hazırlayan fonksiyon.
void lcdSolaKaydir(void);

void main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;

  P1DIR = 0xF2;           // P1.1 (TXD) ve P1.4 - P1.7 (LCD) çıkış.
  P1OUT = 0x02;           // P1.1 idle durumda "1" olmalı.
  P1IE = 0x04;            // P1.2 (RXD)'den kesme gelecek.
  P1IES = 0x04;           // Kesme düşen kenarda gelecek. (Start biti)
  P2DIR = 0xFF;
  P2SEL = 0x00;
  TACCR0 = 108;           // 1000000/9600 = 104. Kritik zamanlama olmaması için biraz arttırdım.
  TACCTL0 = CCIE;         // Timer kesmesine izin ver.
  __enable_interrupt();   // Genel kesmelere izin ver.

  char metin[40] = {0};   // Gelen veri komut değilse bu stringin sonuna ekleniyor.
  int i = 0;

  lcdHazirla();           // LCD hazırlandı.
  lcdBekle(20);

  lcdHucreyeGit(1, 1);    // 1. satır 1. sütuna git.
  lcdYaziYaz("Veri bekleniyor.");

  while(1)                      // Sonsuz döngü içinde,
  {
    if(rs232Alindi)             // Veri alındıysa,
    {
      rs232Alindi = 0;          // Alındı bayrağını temizle.

      switch(rs232Gelen)        // Gelen veriye bak,
      {
        case 20:                // 20 ise,
        {
          lcdYaziYaz(metin);    // Tutulan stringi LCD'ye gönder.
          for(i = 0 ; i < 40 ; i++)   // Stringin tüm karakterlerini
            metin[i] = 0;       // null yap.
          i = 0;                // i'yi sıfırla.
          break;
        }

        case 21:                // 21 ise,
        {
          lcdHucreyeGit(1, 1);  // 1. satır 1. sütuna git.
          break;
        }

        case 22:                // 22 ise,
        {
          lcdHucreyeGit(2,1);   // 2. satır 1. sütuna git.
          break;
        }

        case 23:                // 23 ise,
        {
          lcdSolaKaydir();      // lcdSolaKaydir fonksiyonunu çağır.
          break;
        }

        case 24:                // 24 ise,
        {
          lcdTemizle();         // lcdTemizle fonksiyonunu çağır,
          lcdBekle(3);          // bir süre bekle.
          break;
        }

        default:                // Eğer bu komutlardan biri değilse,
        {
          metin[i++] = rs232Gelen;  // Gelen veriyi stringin sonuna ekle.
        }
      }
    }
  }
}

void rs232Gonder(int rs232GidenFonk)
{
  if(rs232Gonderilecek == 0)      // Eğer o anda veri gönderilmiyorsa,
  {
    rs232Giden = rs232GidenFonk;  // Fonksiyona gönderilen değeri global giden değişkenine al.
    rs232Giden = rs232Giden << 1; // 1 bit sola kaydırarak start biti eklendi.
    rs232Giden += 512;            // En sola stop biti eklendi.
    rs232Gonderilecek = 1;        // Gönderilecek bayrağı set edildi.
    rs232Bit = 0;                 // 0. bitten başlanacak.
    TACTL = TASSEL_2 + ID_0 + MC_1 + TACLR;   // SMCLK + Div = 1 + Up mod + Sıfırla.
  }
}

#pragma vector = PORT1_VECTOR
__interrupt void portKesmesi (void)
{
  if(P1IFG_bit.P1IFG_2)       // Kesme P1.2'den geldiyse,
  {
    if(rs232Alinacak == 0)    // Eğer o anda veri alınmıyorsa,
    {
      rs232Gelen = 256;       // Gelen veriyi 256 yap. Bu şekilde bit bit kaydırırken olası sıkıntı engellenecek.
      rs232Alinacak = 1;      // Alınacak bayrağını 1 yap.
      rs232Bit = 0;           // 0. bitten başlanacak.
      TACTL = TASSEL_2 + ID_0 + MC_1 + TACLR;   // SMCLK + Div = 1 + Up mod + Sıfırla
    }
    P1IFG_bit.P1IFG_2 = 0;    // P1.2 kesme bayrağını temizle.
  }
}

#pragma vector = TIMERA0_VECTOR
__interrupt void timerKesmesi (void)
{
  if(rs232Alinacak == 1)              // Eğer veri alınacaksa,
  {
    if(rs232Bit < 9)                  // Toplam 9 bit alınacak. 8 bit veri + 1 stop biti.
    {
      rs232Gelen = rs232Gelen >> 1;   // Zaman geldiğinde gelen veriyi 1 bit sağa kaydır,
      if(P1IN_bit.P1IN_2 == 1)        // Eğer bit "1" ise,
      rs232Gelen += 256;              // Gelen verinin en soldaki bitine 1 yaz. (2^8, 8. bit)
    }
    else                              // 9 bit de alındıysa,
    {
      TACTL = MC_0;                   // Timerı durdur.
      rs232Gelen -= 256;              // Veriden stop bitini ayıkla.
      rs232Alinacak = 0;              // Alınacak bayrağını "0" yap.
      rs232Alindi = 1;                // Alındı bayrağını "1" yap.
    }
  }

  if(rs232Gonderilecek == 1)
  {
    if(rs232Bit < 10)   // Toplam 10 bit gidecek. 8 bit veri + 1 start biti + 1 stop biti.
    {
      P1OUT_bit.P1OUT_1 = rs232Giden & BIT0;  // Giden verinin 0. bitini P1.1'e bas.
      rs232Giden = rs232Giden >> 1;           // Giden veriyi 1 bit sağa kaydır.
    }
    else                      // Eğer 10 bit de gönderilmişse,
    {
      TACTL = MC_0;           // Timerı durdur.
      rs232Gonderilecek = 0;  // Gönderilecek bayrağını sıfırla.
    }
  }
  rs232Bit++;       // Zaman geldikçe kaçıncı bitte olduğumuz artacak.                           
}

void lcdSolaKaydir(void)
{
  lcdGonder('k', 0x18);             // LCD için sola kaydır komutu.
  lcdBekle(10);                     // Bir süre bekleniyor.
}

Yorum satırları her şeyi açıklıyor. Bu yüzden kodun çalışmasına değinmeyeceğim. RS232 ve LCD için yazdığım yazılarda (bağlantıları bu yazının ilk paragrafında bulabilirsiniz) detaylı olarak olayların işleyişini anlatmıştım. İlgilenenler o yazılarımı inceleyebilir.

Gelelim uygulama için hazırladığım bilgisayar yazılımına. Kaynak kodları çok uzun olacağından buraya eklemeyeceğim. Ancak yazının sonundaki bağlantıdan kodları indirebilirsiniz. Programın şöyle bir arayüzü var :

LCD Arayüzü

LCD Arayüzü

Önce programın kullanılışından bahsedeyim. Sol üstteki Bağlantı kısmından port ayarlarınızı girerek Bağlan butonuna tıklıyorsunuz. Bağlantı sağlandığında isterseniz Debug kısmından komut ve metin gönderebilirsiniz. Komut kısmına girdiğiniz integer değer gönderilmektedir. Böylece 24 gönderip ekranı temizleyebilir, sonrasında da sırasıyla 65 ve 20 göndererek ‘A’ karakterini ekranda görebilirsiniz. Ya da hemen altındaki metinkutusundan metin gönderebilir, daha sonra Komut olarak 20 göndererek metni LCD’de görebilirsiniz.

Alt kısımdaki 1. Satır ve 2. Satır bölümlerinden ilgili satırda ne görüntülemek istediğinizi ayarlayabilirsiniz. RSS seçmeniz durumunda girdiğiniz XML besleme adresinden beslemeler belirlediğiniz kontrol sıklığında kontrol edilecek ve her bir besleme belirlediğiniz süre kadar ekranda kalacaktır. RSS ile favori haber sitenizdeki en son haberleri LCD’niz üzerinden takip edebilirsiniz. Bu arada C# ile RSS okuma hakkında şu sayfadaki yazıdan faydalandığımı belirtmek isterim.

Metin seçiminde direkt olarak oraya girdiğiniz metni LCD üzerinde görebilirsiniz. Bir satırı boş bırakmak istediğinizde ise Metin radio butonunu seçerek ilgili metinkutusuna bir boşluk karakteri yazabilirsiniz. Tarih – Saat seçerseniz, bilgisayarınızın tarih ve saati LCD’de gösterilmekte. Kaydır checkbox’ından yazıyı kaydırmak isteyip istemediğinizi seçebilir, hemen yanından da kayma hızını ayarlayabilirsiniz.

Programı açtığınızda bağlantı yaptıktan sonra satır ayarlarınızı da yapıp Aktarımı Başlat butonuna basmanız yeterlidir. Daha sonra uygulama çalışırken satır ayarlarınızı değiştirmek isterseniz, yeni ayarları girip Seçimi Güncelle butonuna tıklayabilirsiniz. Küçült butonu ile uygulamayı sistem tepsisine küçültebilirsiniz.

Programda 4 adet timer bulunuyor. Bunlardan biri RSS’i kontrol etmek için. Varsayılan olarak 10 dakikada bir beslemeyi kontrol edip bir dosyaya yazıyor. Diğer timer görüntüleme süresi. Zamanı geldiğinde (varsayılan 30 sn.) beslemenin kaydedildiği dosyada satır satır ilerleyerek sıradaki beslemeyi LCD’de görüntülüyor. RSS ve Tarih – Saat seçili ise, bu timer her çalıştığında sistemin saati alınıp LCD’ye yazılıyor. Eğer Tarih – Saat seçili olmasına rağmen RSS seçili değilse 3. bir timer devreye giriyor. Bu da 1 dakikalık aralıklarla sistem saatini kontrol edip LCD’ye gönderiyor. Son timer da kayan yazı için. Kaydırma aktif edildiyse ayarlanan hızda (varsayılan 250 ms.) seri porttan 23 verisini gönderiyor. MSP430 da bunu aldığında yazıyı bir karakter kaydırıyor.

Son olarak devrenin çalışmasından bir video ile yazımı bitiriyorum. C# ve IAR proje dosyalarını ise buradan indirebilirsiniz. C# uygulamasını Visual Studio 2010 ile açıp değişiklikler yapabileceğiniz gibi bin klasöründeki Debug klasörü içinden rs232-lcd.exe dosyasını açarak kullanmaya başlayabilirsiniz.

Share

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>