Picproje Elektronik Sitesi

DERLEYİCİLER => PIC C => Konuyu başlatan: fatihvelid - 05 Temmuz 2007, 13:15:53

Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 05 Temmuz 2007, 13:15:53
Merhaba arkadaşlar, KS108 için driver yazıyorum. Lcd'de doğru çizen ve istediğim piksele nokta koyan fonksiyon yazmak istiyorum.

Nasıl yapabileceğim konusunda yardımcı olabilirmisiniz ? Bu konuda  örnek var mı ?
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: birumher - 05 Temmuz 2007, 14:27:04
Doğru çizmek için Bresenham algoritması kullanabilirsin.

http://tr.wikipedia.org/w/index.php?title=Bresenham%27%C4%B1n_%C3%A7izgi_algoritmas%C4%B1&oldid=1761138 (http://tr.wikipedia.org/wiki/Bresenham%27%C4%B1n_%C3%A7izgi_algoritmas%C4%B1)

adresinde algoritmanın detaylarını bulabilirsin.

Aşağıda da Picc ile yapılmış örnek var.
glcd_pixel() fonksiyonunu yazarsan bunu aynen bu şekilde kullanabilirsin.


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
// Purpose:       Draw a line on a graphic LCD using Bresenham's
//                line drawing algorithm
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                color - ON or OFF
// Dependencies:  glcd_pixel()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
void glcd_line(int x1, int y1, int x2, int y2, int1 color)
{
 signed int  x, y, addx, addy, dx, dy;
 signed long P;
 int i;
 dx = abs((signed int)(x2 - x1));
 dy = abs((signed int)(y2 - y1));
 x = x1;
 y = y1;
 if(x1 > x2)
   addx = -1;
 else
   addx = 1;
 if(y1 > y2)
   addy = -1;
 else
   addy = 1;
 if(dx >= dy)
 {
   P = 2*dy - dx;
   for(i=0; i<=dx; ++i)
   {
     glcd_pixel(x, y, color);
     if(P < 0)
     {
       P += 2*dy;
       x += addx;
     }
     else
     {
       P += 2*dy - 2*dx;
       x += addx;
       y += addy;
     }
   }
 }
 else
 {
   P = 2*dx - dy;
   for(i=0; i<=dy; ++i)
   {
     glcd_pixel(x, y, color);
     if(P < 0)
     {
       P += 2*dx;
       y += addy;
     }
     else
     {
       P += 2*dx - 2*dy;
       x += addx;
       y += addy;
     }
   }
 }
}
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 05 Temmuz 2007, 16:05:55
İlginiz için teşekkür ederim.

İstediğimiz X,Page piksel'ine ekrandaki görüntü üzerinden nasıl nokta koyabilirim?
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 05 Temmuz 2007, 18:00:13
Grafik LCD'nin RAM'ini belleğe kopyalayıp ( 1024 byte )  grafiksel bütün işlemleri bellekte yapsam ve grafik lcd'ye geri yazsam bu yöntem nasıl olur.

Ayrıca yatay ve dikey çizgileri nasıl çizebilirim. Yukarıdaki algoritmayı kullanmadan
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: birumher - 05 Temmuz 2007, 18:16:14
Alıntı yapılan: "fatihvelid"Grafik LCD'nin RAM'ini belleğe kopyalayıp ( 1024 byte )  grafiksel bütün işlemleri bellekte yapsam ve grafik lcd'ye geri yazsam bu yöntem nasıl olur.

Ayrıca yatay ve dikey çizgileri nasıl çizebilirim. Yukarıdaki algoritmayı kullanmadan

Her seferinde 1024 byte veriyi LCD ye göndereceksen pek mantıklı değil gibi geldi bana. Sadece değişenleri göndereceksen olabilir ancak çarpışma testi vs yapmayacaksan neden RAM e kopyalamaya ihtiyacın olsun ki.

Yatay veya dikey çizgi çekmek kolay.

Yatay çizgi için

örneğin başlangıç koordinatları x1,y1 bitiş koordinatları x2,y2 olsun zaten y1 ve y2 eşit olmak zorunda bir döngü kuracaksın x1 den x2 ye kadar

for(i=x1; i<=x2; ++i)
{
 glcd_pixel(i, y1, color);
}

diyeceksin burada x1 x2 den küçük olmalı. Değilse sıralarını değiştirirsin.

dikey çizgi çekmek içinse

for(i=y1; i<=y2; ++i)
{
 glcd_pixel(x1, y, color);
}

diyeceksin. Burada da y1 < y2 olmalı.
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: CLR - 05 Temmuz 2007, 18:23:02
@fatihvelid

GLCD'de 2 tane KS0108 var.
Her chip 8 sayfa,64 sutun'u kontrol eder.
Dolayısıyla 2 tanesi 8 sayfa,128 sutun'u kontrol eder.

Herhangi bir pixel'i yakmak istiyorsan, önce ilgili işlemciyi seçeceksin
sonra pixel sangi sayfadaysa, sayfa kodunu göndereceksin, pixel hangi sutundaysa sutun kodunu göndereceksin, ve son olarak pixel, hangi bit ise
onu 1 yapacaksın diğer 7 bit 0 olacak.

Sayfa ve sutun kodları nedir ve nasıldır diyorsan, GLCD'nin datasheet'ini incele. İçinde ks0108 bulunan tüm datashetlerden faydalanabilirsin.
Glcd'nin bacak bağlantıları dışında farklılık olmaz.

Kolay gelsin.
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: mesmert - 06 Temmuz 2007, 11:37:41
Alıntı yapılan: "fatihvelid"İlginiz için teşekkür ederim.

İstediğimiz X,Page piksel'ine ekrandaki görüntü üzerinden nasıl nokta koyabilirim?


GLCD'ler decimal 184 başlayıp 191 de biter ve toplam 8 sayfadır. senin yapacağın GLCD sayfa bilgisini gönderip daha sonra hangi pixel aftif olmasını istiyorsan hangi bölgede ise onun cipini on yapıp daha sonra pixel değerini gönderiyorsun.
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 06 Temmuz 2007, 12:46:51
İlk çalıştırdığımda çok kısa süre için ekran gidip geliyor. Nedendir acaba.

Ayrıca GLCD'nin RAM'ini okurken bir sorunla karşılaşıyorum. Okumuyor ve hep 0 dönüyor sanırım. Yazdığım kod aşağıda. Bir hata mı var?

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)  
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_Data_TRIS = 0xFF;  
 GLCD_RW = 1;
 GLCD_E = 1;
 Delay1KTCYx(1);
 GLCD_E = 0;
 Delay1KTCYx(1);
 GLCD_E = 1;
 Delay1KTCYx(1);
 Data = GLCD_Data_PORT;
 GLCD_E = 0;  
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 GLCD_Data_TRIS = 0x00;  
 GLCD_RW = 0;
return Data;
}
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: mesmert - 06 Temmuz 2007, 13:09:48
CCS bilmediğim için vereceğim fikir belki işine yarar; KS0108 GLCD okurken dikkat etmen gereken kısım lcd ekran iki ayrı çipten oluştuğu için ilk önce birinci chip aktif yapıp okuyacaksın sonra ise birinci chip off yapıp ikinci chip okuyacaksın
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 06 Temmuz 2007, 13:34:56
CCS kullanmıyorum. Programı C18 ile geliştiriyorum.Kendi oluşturduğum yapıları kullanıyorum.
Yukarıdaki programda, BYTE GlcdRead(CS _cs)  fonksiyonunu çağırmadan önce PAGE ve X eksenini ayarlıyor. Ve ardından CS'lerden sadece birisini aktif yapıyor.

RW = 1 olduğunda E'nin düşen kenarında veriyi almaya çalışıyor.
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: CLR - 06 Temmuz 2007, 14:50:30
Okuma ve yazmada bilmen gereken en önemli noktalar şunlar

1) GLCD'ye Yazma yapacaksan E'nin düşen kenarında yazılır
   GLCD'den bir data okuyacaksan E=1 iken okunur

2) Data okuyacakken veya yazacakken  LCD meşgul mu değilmi bilmelisin yani ilk önce busy flag okunur.


Kolay gelsin
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 06 Temmuz 2007, 15:03:54
Alıntı yapılan: "eemkutay"Okuma ve yazmada bilmen gereken en önemli noktalar şunlar

1) GLCD'ye Yazma yapacaksan E'nin düşen kenarında yazılır
   GLCD'den bir data okuyacaksan E=1 iken okunur

2) Data okuyacakken veya yazacakken  LCD meşgul mu değilmi bilmelisin yani ilk önce busy flag okunur.


Kolay gelsin


Busy Flag'ı nasıl okuyabilirim. Ve işlemler arasına ne kadar gecikme koymam gerekiyor.


Aşağıdaki kod'da sorun olmasa gerek.


BYTE GlcdRead(CS _cs)
{
BYTE Data;
if(_cs == CS2)
GLCD_CS2 = TRUE;
else
GLCD_CS1 = TRUE;
GLCD_Data_TRIS = 0xFF;
GLCD_RW = 1;
GLCD_E = 1;
Delay1KTCYx(1);
GLCD_E = 0;
Delay1KTCYx(1);
GLCD_E = 1;
Delay1KTCYx(1);
Data = GLCD_Data_PORT;
GLCD_E = 0;
GLCD_CS1 = FALSE;
GLCD_CS2 = FALSE;
GLCD_Data_TRIS = 0x00;
GLCD_RW = 0;
return Data;
}

Kolay Gelsin
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: CLR - 06 Temmuz 2007, 16:52:22
Karakter LCD'deki gibi araya delay koyarak bu iş çözülmez. Çünkü GLCD üreticisi, "GLCD'nin işlemleri şu kadar zaman alır " gibi kesin bilgiler vermiyorlar dolayısıyla  glcd içindeki status registerinin 7 biti busy flag'dir. Bu flag kontrol edilir. Busy flag 0 ise data yazabilir veya okuyabilirsin.

Arada gereksiz enable'ların vardı kaldırdım


// Bu kod data okumak içindir status'u okumaz, statusu okumak için
// diğer kısımları kullanmalısın ( // ile yazdığım)

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
// GLCD_RS=0;                   // busy için
 GLCD_RS=1;
 GLCD_RW = 1;
 GLCD_E=1;

 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.

// oku:
 Data = GLCD_Data_PORT;    
//  if(Data&&0x80)                // 7.bit testi yapıyoruz
//  goto    oku;                     // LCD meşgul

 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 GLCD_Data_TRIS = 0x00;
 GLCD_RW = 0;
 return Data;
}
 
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 09 Temmuz 2007, 13:31:35
Alıntı yapılan: "eemkutay"

// Bu kod data okumak içindir status'u okumaz, statusu okumak için
// diğer kısımları kullanmalısın ( // ile yazdığım)

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
// GLCD_RS=0;                   // busy için
 GLCD_RS=1;
 GLCD_RW = 1;
 GLCD_E=1;

 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.

// oku:
 Data = GLCD_Data_PORT;    
//  if(Data&&0x80)                // 7.bit testi yapıyoruz
//  goto    oku;                     // LCD meşgul

 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 GLCD_Data_TRIS = 0x00;
 GLCD_RW = 0;
 return Data;
}
 


Düzenleyip aşağıdaki hale getirdim. Ama yine biryerlerde sorun var. PIC 40 MHZ'de çalışıyor. Hızdan kaynaklanan bir sorun olabilir mi ?

Yanlışım varsa düzeltirmisiniz ?

Alıntı Yap


BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_RW = 1;
 GLCD_DI = 1;
 GLCD_E=1;
 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.
 Glcd_Wait_Busy();  
 _asm
 nop
 nop
 nop
 nop
 nop
 _endasm
 Data = GLCD_Data_PORT;    
 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 return Data;
}

void Glcd_Wait_Busy(void)
{
BYTE status;
GLCD_DI = 0;
GLCD_RW = 0;
GLCD_Data_TRIS = 0xff;
_asm
nop
nop
nop
_endasm

while(1)
{
GLCD_E = 1;
_asm
nop
nop
nop
_endasm
status = GLCD_Data_PORT;
if ((status & 0x80) == 0)
break;
_asm
nop
nop
nop
_endasm
}
GLCD_Data_TRIS = 0x00;
GLCD_RW = 0;
}

İlgileriniz için teşekkürler. Kolaya gelsin
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: CLR - 09 Temmuz 2007, 19:01:19
Alıntı Yap

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_RW = 1;
 GLCD_DI = 1;
 GLCD_E=1;
 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.
 Glcd_Wait_Busy();              
 _asm
 nop
 nop
 nop
 nop
 nop
 _endasm
 Data = GLCD_Data_PORT;    
 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 return Data;
}

void Glcd_Wait_Busy(void)
{
BYTE status;
GLCD_DI = 0;
GLCD_RW = 0;
GLCD_Data_TRIS = 0xff;
_asm
nop
nop
nop
_endasm

while(1)
{
GLCD_E = 1;
_asm
nop
nop
nop
_endasm
status = GLCD_Data_PORT;
if ((status & 0x80) == 0)
break;
_asm
nop
nop
nop
_endasm
}
GLCD_Data_TRIS = 0x00;
GLCD_RW = 0;
}

İlgileriniz için teşekkürler. Kolaya gelsin[/quote]

Elindeki Glcd'nin datasheet'in deki zamanlama tablosunu ve diyagramını incelemelisin. 40Mhz çok yüksek hız, bir komut 100ns , programda hatalar  var ve zamanlama problemin olmaması için dediğim gibi zaman haberleşme diyagramını incele , benim kullandığım glcd, hy12864 ve clock puls'i en az 450ns diyor ve ben 20mhz'de 3 tane nop atıyorum (600ns) herşey ok.

Zamanlama diyagramındaki zamanlardan biraz daha yavaş çalıştırırsan , sorun olmayacaktır.

Programında hatalar var, busy test fonksiyonun kullanım yeri hatalı,
ilk önce busy testi yapılır sonra read işlemi yapılır, aşağıdaki gibi



Glcd_Wait_Busy();    // lcd meşgul mu? meşgul değilse aşağı satıra geçer
Glcd_Read(1);          // Daha önce girdiğin adresi 1. chip'ten okur

// read programında hata vardı düzeltildi, aşağıdaki gibi olacak ama yine
// datasheet'ten zamanlamaları kontrol etmelisin bu nedenle nop'lara
// dokunmadım

BYTE GlcdRead(CS _cs)
{
 BYTE Data;
 if(_cs == CS2)
 GLCD_CS2 = TRUE;
 else
 GLCD_CS1 = TRUE;
 GLCD_RW = 1;                   // datasheet'e göre bu seviye aralarına
 GLCD_DI = 1;                    // nop'lar gerekebilir
 GLCD_E=1;
 GLCD_Data_TRIS = 0xFF;   // hem port ayarlıyorum hemde delay oluy.    
 _asm
 nop
 nop                                  
 nop                                    // en az nop için dahasheet'e bakmalısın
 nop
 nop
 _endasm
 Data = GLCD_Data_PORT;    
 GLCD_E = 0;
 GLCD_CS1 = FALSE;
 GLCD_CS2 = FALSE;
 return Data;
}

// burada her iki chip busy mi test ediliyor istersen adrese göre
// yapabilirsin

void Glcd_Wait_Busy(void)
{
GLCD_CS1=1;                          //1.chip on, diğeri zaten off
busy_test( );                            // busy flag=0 oluncaya kadar bekle
GLCD_CS1=0;
GLCD_CS2=1;                         //2.chip on, diğeri  off
busy_test( );                           // busy flag=0 oluncaya kadar bekle
}

// tek chip busy mi test ediyor
void busy_test(void)
{
BYTE status;
GLCD_DI = 0;                          // komut modu
GLCD_RW = 1;                        // okuma modu
GLCD_E = 1;                           // data okuyacağız, E=1
GLCD_Data_TRIS = 0xFF;        // portlar giriş
_asm
nop
nop
nop
_endasm

while(1)
{
_asm
nop
nop
nop
_endasm
status = GLCD_Data_PORT;        // portu oku
if (status & 0x80)                       // busy flag =0 ise çık
break;
_asm
nop
nop
nop
_endasm
}
GLCD_Data_TRIS = 0x00;          // port çıkış
GLCD_E = 0;                             // E=0
}
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 11 Temmuz 2007, 10:11:09
Teşekkür ederim.

Lcd'de resim göstermek istiyorum. Fonksiyonuda yazdım. Resmi gösterdiğimde bazen resmin bir kısmı aşağı kayıyor. Bazende doğru gösteriyor.

Bir türlü çözemedim. Algoritmada bir hata olmadığına eminim. Bir bakabilirmisiniz ?

Alıntı Yap
void Glcd_Image(rom unsigned char *image)
{
   BYTE x=0,y=0;
   auto unsigned int i=0;    
   while(1)
   {      
     GLCD_DI = 0;
     _asm nop nop nop nop nop
       _endasm
     GlcdWrite(CS1,0x40);
     GlcdWrite(CS1,0xB8 | y);
     GLCD_DI = 1;    
     for(x=0;x<=63;x++,i++)
     GlcdWrite(CS1,image);    
       GLCD_DI = 0;
       GlcdWrite(CS2,0x40);
       GlcdWrite(CS2,0xB8 | y);
       _asm nop nop nop nop nop
       _endasm
       GLCD_DI = 1;      
     for(x=0;x<=63;x++,i++)
     GlcdWrite(CS2,image);
     if(i>1023)
     break;
     y++;  
   }

}

Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: CLR - 11 Temmuz 2007, 15:21:46
GLCD'ye data yazmayı ve okumayı başardın, bundan sonrası kolay ve gerisi sana kalmış.

Resimleri I2C 400Khz'de haberleşebilen eeprom'a yüklüyorum. Oradan 380Khz civarında bir hızla okuyorum ve ekrana yazdırıyorum. 32KB'lık bir eeproma 32 adet 128x64'lük full ekran yüklenebiliyor. Ayrıca karakter tablosunu da resim olarak gösteriyorum ve karaktere göre eepromda adres gösterip okutturuyorum. Böylece işlemcinin hafızasını gereksiz kodlarla doldurmuyorum.

Kolay gelsin.
Başlık: Grafik Lcd'de doğru çizmek,
Gönderen: fatihvelid - 11 Temmuz 2007, 17:08:05
Sorunları çözdüm. Yardımlarınız için teşekkürler.
PIC18F8722'nin flash kapasitesi 128kb olduğu için eeproma kaydetmeye gerek olmaz. Zaten birkaç tane resim kaydedeceğim.  

C için istediğimiz fontu üreten bildiğiniz ücretsiz program var mı ?

Tekrar teşekkürler.