Jump to page: 1 2
Thread overview
D ile LCD panel kontrolü
Jul 30, 2012
erdem
Jul 30, 2012
erdem
Jul 30, 2012
mert
Jul 30, 2012
Salih Dinçer
Jul 30, 2012
Salih Dinçer
Jul 30, 2012
erdem
Jul 31, 2012
erdem
Aug 01, 2012
erdem
Aug 02, 2012
erdem
July 30, 2012

Bir kaç günder D ile LCD panel uygulamasını nasıl yapayım diye düşünüyorum. Ama işin içinden çıkamadım :rolleyes:

Kodun en son hali şu şekilde:

import std.stdio;
import giriscikis;
import core.thread;

version (linux)
{
   /*
     paralel portun adresi
   */
   const uint adres = 0x0378;

   const uint kontrol = 0x037A;

   /*
     göndereceğimiz veri
   */
   ubyte veri = 0b0000;

   const ubyte Komut = 0b1000;    // komut
   const ubyte Veri  = 0b0000;     // veri

   const ubyte E1  = 0b0000; /+ veri   +/
   const ubyte E0  = 0b0001; /+ gönder +/

   const ubyte EkranıTemizle = 0b00000001;
   const ubyte PaneliAç = 0b00001100;
}


void main()
{

   version(linux)
   {
       /*
           Linux'ta paralel porta erişmek için yönetici haklarını alıyoruz
       */
       erişimhakları(adres, 1, 1);
       erişimhakları(kontrol, 1, 1);
   }

   version (Windows)
   {
       /*
         paralel portun adresi
       */
       short adres = 0x0378;

       /*
           göndereceğimiz veri
       */
       short veri = 0b1111;
   }

   komutGönder(EkranıTemizle);
}

void komutGönder(ubyte veri)
{
   yaz(kontrol, Komut);
   yaz(kontrol, E1);
   yaz(adres, veri);
   yaz(kontrol, E0);
   Thread.sleep(dur!"usecs"(40));
}

Şimdi burada ilk sormak istediğim işletim sistemine bağlı olan kısımları ister istemez global değişken yaptım. Bu kısımları kod tekrarı olmaması açısından tek bir kaynak dosyasına toplasam mı.

Bir diğeri de sizin de dikkat edeceğiniz gibi kodun okunabilir olması adına Komut, Veri, EkranıTemizle gibi bir sürü ek değişken kullanmak zorunda kaldım. Yoksa basitçe bu mesajdaki gibi (http://ddili.org/forum/thread/678) sayısal değerler kullanıp bu değişkenlerden kurtulsamıydım.

Şimdi LCD panele komut ya da veri gönderme şu şekilde oluyor. 'RS' 0 iken komut 'RS' 1 iken veri göndereceğimizi belirtiyoruz. 'Enable '(LCD aktif) bitini 1'den 0 yaptığımız zaman da veri ya da komut gönderiliyor.

Şu şekilde göstermek gerekirse

RS . . E
1 0 0 0

Örneğin burada RS0 yapmak için donanım tarafından terslendiği için 1000 göndermek gerekiyor.

Bir de bu şekilde kodu daha okunabilir yapmak için değişken kullandığımızda bir sürü birbirine bağlı değişken de var. Örneğin

0 0 0 0 0 1 P İ Y

Yukarıda paneli aç değişkeni 00001100 şeklinde tanımlı. Ama kullanıcı örneğin aynı zamanda paneli aç, imleci aç, yanıp sönmeyi aç demek isterse 00001111 şeklinde komut gönderebilir. Yani değişkenler birbirine bağımlı.

Kısacası yazdığım kodu pek şık bulmadım. Enum falan mı kullansaydık acaba .. Şimdilik işin içinden çıkamadım

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Vay ben bunu nasıl düşünememişim :-)

Peki sizce işletim sistemine bağlı olan kısımlar ayrı bir modüle gitsin mi. Bir de bir baytlık bir değişkenin her biti farklı bir değer ifade edebiliyorsa bunun için hangi değişken türü sizce uygun olur. Birlikler buna benzer bir şeyler yapıyor ama o farklı galiba.

Çok süper bir ipucu :-D Malum Ramazan ayı olduğu için biraz vakit az kalıyor yavaş yavaş yapabiliyorum.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Güzel yaklaşım. Böyle böyle çeşitleniyor bilgilerimiz. Erdem hazır değerler için enum kullanmayı düşünmen de mantıklı gibi görünüyor buradan bana.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Bence 4 işleve ihtiyacın var:

  • lcd_init()
  • lcd_putc()
  • lcd_getc()
  • lcd_gotoxy()

Bunları gerçekleştirdikten sonra printLCD() diye başka bir işlevi öncekiler ile uyumlu çalışmasını sağlamalısın. Ayrıca lcd_init() belli parametreler alabilir. Çünkü farklı satır/sütun boyutlarında olacaktır. Ekrana yazılırken bunların dikkate alınması gerekecektir.

Global variable'a gelince; bence alias kullanmak çok daha pratik sonuçlar doğuracaktır.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Ahan da şimdi bulduğum şu kodlar çok çok işine yarayacaktır...:)

// Flex_LCD420.c

// These pins are for my Microchip PicDem2-Plus board,
// which I used to test this driver.
// An external 20x4 LCD is connected to these pins.
// Change these pins to match your own board's connections.

#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_D5
#define LCD_DB6   PIN_D6
#define LCD_DB7   PIN_D7

#define LCD_RS    PIN_E0
#define LCD_RW    PIN_E1
#define LCD_E     PIN_E2

/*
// To prove that the driver can be used with random
// pins, I also tested it with these pins:
#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_B1
#define LCD_DB6   PIN_C5
#define LCD_DB7   PIN_B5

#define LCD_RS    PIN_E2
#define LCD_RW    PIN_B2
#define LCD_E     PIN_D6
*/

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.  Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD.  It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit.  Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.

#define USE_RW_PIN   1

// These are the line addresses for most 4x20 LCDs.

#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/


//========================================

#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)

int8 lcd_line;

int8 const LCD_INIT_STRING[4] = {
  0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
  0xc,                     // Display on
  1,                       // Clear display
  6                        // Increment cursor
};

//-------------------------------------
void lcd_send_nibble(int8 nibble) {
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
  output_bit(LCD_DB4, !!(nibble & 1));
  output_bit(LCD_DB5, !!(nibble & 2));
  output_bit(LCD_DB6, !!(nibble & 4));
  output_bit(LCD_DB7, !!(nibble & 8));

  delay_cycles(1);
  output_high(LCD_E);
  delay_us(2);
  output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_RW_PIN
  int8 lcd_read_nibble(void) {
     int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
     #bit retval_0 = retval.0
     #bit retval_1 = retval.1
     #bit retval_2 = retval.2
     #bit retval_3 = retval.3

     retval = 0;

     output_high(LCD_E);
     delay_us(1);

     retval_0 = input(LCD_DB4);
     retval_1 = input(LCD_DB5);
     retval_2 = input(LCD_DB6);
     retval_3 = input(LCD_DB7);

     output_low(LCD_E);
     delay_us(1);

     return(retval);
  }
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_RW_PIN
  int8 lcd_read_byte(void) {
     int8 low;
     int8 high;

     output_high(LCD_RW);
     delay_cycles(1);

     high = lcd_read_nibble();

     low = lcd_read_nibble();

     return( (high<<4) | low);
  }
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n) {
  output_low(LCD_RS);

  #ifdef USE_RW_PIN
     while(bit_test(lcd_read_byte(),7)) ;
  #else
     delay_us(60);
  #endif

  if(address)
     output_high(LCD_RS);
  else
     output_low(LCD_RS);

  delay_cycles(1);

  #ifdef USE_RW_PIN
     output_low(LCD_RW);
     delay_cycles(1);
  #endif

  output_low(LCD_E);

  lcd_send_nibble(n >> 4);
  lcd_send_nibble(n & 0xf);
}
//----------------------------

void lcd_init(void) {
  int8 i;

  lcd_line = 1;

  output_low(LCD_RS);

  #ifdef USE_RW_PIN
     output_low(LCD_RW);
  #endif

  output_low(LCD_E);

// Some LCDs require 15 ms minimum delay after
// power-up.  Others require 30 ms.  I'm going
// to set it to 35 ms, so it should work with
// all of them.
  delay_ms(35);

  for(i=0 ;i < 3; i++) {
     lcd_send_nibble(0x03);
     delay_ms(5);
  }

  lcd_send_nibble(0x02);

  for(i=0; i < sizeof(LCD_INIT_STRING); i++) {
     lcd_send_byte(0, LCD_INIT_STRING[i]);

// If the R/W signal is not used, then the busy bit can't be polled.  One of
// the init commands takes longer than the hard-coded delay of 50 us, so in
// that case, lets just do a 5 ms delay after all four of them.

     #ifndef USE_RW_PIN
        delay_ms(5);
     #endif
  }
}

//----------------------------
void lcd_gotoxy(int8 x, int8 y) {
  int8 address;
  switch(y) {
     case 1:
        address = LCD_LINE_1_ADDRESS;
        break;
     case 2:
        address = LCD_LINE_2_ADDRESS;
        break;
     case 3:
        address = LCD_LINE_3_ADDRESS;
        break;
     case 4:
        address = LCD_LINE_4_ADDRESS;
        break;
     default:
        address = LCD_LINE_1_ADDRESS;
        break;
  }
  address += x-1;
  lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c) {
  switch(c) {
     case '\a':
        lcd_gotoxy(1, 1);
        lcd_line = 1;
        break;
     case '\f':
        lcd_send_byte(0,1);
        lcd_line = 1;
        delay_ms(2);
        break;
     case '\n':
        if(lcd_line==4) lcd_line=0;
        lcd_gotoxy(1, ++lcd_line);
        break;
     case '\b':
        lcd_send_byte(0,0x10);
        break;
     default:
        lcd_send_byte(1,c);
        break;
  }
}

//------------------------------
#ifdef USE_RW_PIN
  char lcd_getc(int8 x, int8 y) {
     char value;
     lcd_gotoxy(x,y);

// Wait until busy flag is low.
     while(bit_test(lcd_read_byte(),7));

     output_high(LCD_RS);
     value = lcd_read_byte();
     output_low(LCD_RS);

     return(value);
  }
#endif

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Alıntı (acehreli):

>

Bu arada, benim de sık sık unuttuğum bir şey: D'de global değişken yok; en dış olarak modül düzeyinde değişken olabiliyor. (Bu konuyla ilgili değil ama eklemek istedim. :))

Bunu gösterdiğiniz/hatırlattığınız için teşekkürler..

Alıntı (acehreli):

>

D'nin gücünün güzel bir örneği olan std.bitmanip.bitfields:

http://dlang.org/phobos/std_bitmanip.html

Eğer std.bitmanip düşündüğüm gibi çalışıyorsa bu noktadan sonra kod yazmak zevkli bir hale gelebilir :-)

Alıntı (Salih Dinçer):

>

Ahan da şimdi bulduğum şu kodlar çok çok işine yarayacaktır...:)

Teşekkürler C mi bu :-)

Ama biraz D koduyla karşılaştırılınca ilkel gibi kalıyor. Örneğin D ile Türkçe karakterleri bile LCD panele basitçe şu şekilde gönderebiliyorduk.

   foreach (wchar harf; mesaj) {
       switch(harf) {
           case('ç'):
               veriGönder(0);
               break;
           /* ... */
           default:
               veriGönder(cast(ubyte)(harf));
               break;
       }
   }

Aslında ben de buna benzer bir kodu PIC ile sıcaklık uygulamaları konusunda kullanmıştım ;-)

https://github.com/erdemoncel/sicaklik/blob/master/lcd.c

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Bence bu artık bir sınıf tanımlamayı gerektirmiş. Sanki bir LcdPanel nesnem olsa da bu panelle yapabildiğim işlemleri o nesne üzerinden halletsem:

   auto l = new LcdPanel(/* ... varsa parametreleri */);
   l.yaz("merhaba");
   l.sil();
   // vs.

Belki sen de sonunda bunu sağlayacaksındır. :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 30, 2012

Alıntı (erdem):

>

işletim sistemine bağlı olan kısımlar ayrı bir modüle gitsin mi

Bu modülün çok özel bir işi olduğu için bu modülde kalmasında sakınca görmüyorum. Eğer bilmediğim onlarca başka sabit varsa belki o zaman düşünürsün.

Bu arada, benim de sık sık unuttuğum bir şey: D'de global değişken yok; en dış olarak modül düzeyinde değişken olabiliyor. (Bu konuyla ilgili değil ama eklemek istedim. :))

Alıntı:

>

Bir de bir baytlık bir değişkenin her biti farklı bir değer ifade edebiliyorsa bunun için hangi değişken türü sizce uygun olur.

D'nin gücünün güzel bir örneği olan std.bitmanip.bitfields:

http://dlang.org/phobos/std_bitmanip.html

C ve C++'ta iç olanaktır; D'de kütüphane olarak gerçekleştirilebilmiştir.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 31, 2012

Şimdilik gerçek devre üzerinde test etmedim ama 'std.bitmanip' kullanınca şunun gibi bir şey ortaya çıktı.

import std.stdio;
import std.bitmanip;

struct EkranSeçenekleri
{
   union
   {
       ubyte değeri;
       mixin(bitfields!(ubyte,"", 4,
                        bool, "aktif", 1,
                        bool, "panelaç", 1,
                        bool, "imleçaç", 1,
                        bool, "yanıpsönme", 1));
   }
}

void komutGönder(ubyte veri)
{
   yaz(0x037A, veri);
}

void yaz(uint adres, ubyte değer)
{
}

void main()
{
   EkranSeçenekleri seçenekler;
   seçenekler.aktif = true;
   seçenekler.panelaç = true;
   seçenekler.imleçaç = true;
   seçenekler.yanıpsönme = true;
   komutGönder(seçenekler.değeri);
}

Şimdilik varsayılan ilklendirme (http://forum.dlang.org/thread/edzxxcjgdhphghytzcvn@forum.dlang.org) kullanamıyoruz sanırım.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 31, 2012

Eğer olacaksa, varsayılan değerler herhalde bir sonraki sürümde olur.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2