Merhaba Arkadaşlar. Bu yazımda P10 LED Panellerin Mikrodenetleyici ile sürülmesi hakkında bilgi vereceğim. P10 LED Paneller son birkaç yıldır moda oldu ve piyasada oldukça sağlam bir yer sahibi oldu. Gerçekten nerdeyse heryerde bu paneller kullanılarak yapılmış irili ufaklı grafik ekranlara rastlayabilirsiniz.
Normalde Bu paneller için çeşitli özelliklere sahip sürücü kartları bulabilirsiniz. Amacımız bu kartların yapamıyacağı kendi özel projelerinizde bu panelleri kullanmak. Bende bu noktadan yola çıktım.
Herneyse işin ayrıntılarına girmeden önce bazı teknik detayları belirtmek isterim. Bu panelleri kontrol etmek işlem yoğunluğu olan bir iş, Bu yüzden paneli sürecek olan mikrodenetleyici oldukça yüksek frekanslarda çalışması gerekiyor. Bu yüzden bende 18F serisi ve 40Mhz çalışma frekansını seçtim. 2-3 veya 4 paneli bu hızlarda idare edebilirsiniz fakat fazlası için hızın artması gerekir.
Panel Spi ile Haberleşiyor. üzerinde 16 adet 74595 Shift Register bulunmakta. Bu Shift Registerler dizilişi icabı her biri ayrı bir bölümdeki ledleri kontrol etmektedir.
74595 lerin Panel içerisindeki yapısı resimdeki gibidir.
Displayi Sürmek için 74595 lere datalar gönderildikten sonra A ve B ucları konumlandırılıp OE pini 1 Konumuna çekilerek Display Aktif hale getirilir. Ardından belirli bir süre kadar beklenip OE pini 0 konumuna çekilerek yeniden data gönderilir. Sonra Tekrar A ve B pinleri konumlandırılıp Tekrardan OE pini 1 konumuna çekilip display aktif edilir. Panelin sürülüş tarzı bu şekildedir.
Örneğin; aşağıda ki Tablodan örnek vermek gerekirse, A=0, B=0 ike Sadece Kırmızı ile renklendirdiğim satırlar aktif olur.
A=1 B=0 iken Mavi, A=0 B=1 iken Yeşil, A=1 B=1 iken Sarı Satırlar Aktif olur. Tarama ve Data gönderme işlemi buna göre yapılmaktadır.
P10 LED Panel’de bir önceki data gönderimi ile bir sonraki data gönderimi arasındaki bekleme biraz önemlidir. Çok Fazla beklemek Display parlaklığını çok arttırıyor. Fakat panelde tümü yanıyorken 5Ampere yakın akım çekiyor. Çok fazla bir değer. Normalde Panelin 4 Amperden fazla akım çekmesine engel olmak gerekiyor. Aksi halde Arkadaki sürücü enteğreler biraz ısınıyorlar. Bu dediğim süreler 500uS ile 2000uS arasındadır.
Normalde 1000uS en ideali ama ben 800uS bekledim.
Şimdi Panel Hakkında biraz bilgimiz olduğuna göre artık donanıma ve yazılıma bakabiliriz.
Burada ben PIC18F4620 kullandım. 4xPLL ile 40Mhz de çalıştırdım. Ayrıca donanımsal spi modülünü kullanarak Data gönderiminde max. hıza ulaşmaya çalıştım. Donanımsal spi ile yazılımsal spi arasında oladukça fazla bir hız farkı var.
Panel ile Pic arasındaki bağlantılar aşağıda verdiğim şemadaki gibidir.
Paneli ilk başta elime aldığımda açıkçası nasıl süreceğim hakkında hiçbir fikrim yoktu. Nasıl çalıştığını öğrendikten sonra kendim ekran için bir ram bölgesi ayırıp bu ram bölgesini Timer Kesmesi ile sürekli Ekrana yansıttım. Bu iş için iki boyutlu bir dizi kullandım.
Ekranın ram yapısını aşağıdaki tablodan görebilirsiniz.
Bu ram bölgesini ekrana yansıtmak için Timer kesmesini kullandım. Timer kesmesini 800uS de bir oluşacak şekilde ayarladıktan sonra her kesme oluştuğunda displaya_ram isimli dizinin ilgili bölgesini ekrana gönderip, bilginin gözükecegi satır aktif edilir. Bu işlem sürekli devam etmesi gerekir.
Aşağıdaki kodda timer kesme fonksiyonu ve ram alanını displaye göndermek için hazırladığım Spi data gönderme fonksiyonu var.
Timer Kesme fonksiyonu
#int_timer0 //Timer0 Kesmesi void Timer0_int(){ set_timer0(133); //800us Gecikme için Timer kuruluyor.. output_toggle(pin_d1); switch (int_syc) //Her 800us de Bir bir sonraki satıra Geç { case 0: output_low(PinOE);write_data(int_syc); output_low(PinA);output_low(PinB);output_high(PinOE); break; case 1: output_low(PinOE);write_data(int_syc); output_high(PinA);output_low(PinB);output_high(PinOE); break; case 2: output_low(PinOE);write_data(int_syc); output_low(PinA);output_high(PinB);output_high(PinOE); break; case 3: output_low(PinOE);write_data(int_syc); output_high(PinA);output_high(PinB);output_high(PinOE); break; } int_syc++;if(int_syc>3)int_syc=0; }
Spi Data gönderme Fonksiyonu
void write_data(unsigned int8 row_adr) { int8 i=0,j=0; int8 k=3; while(k!=255) // Bu Döngü ileriye doğru sayarsa panel sağdan {j=15-k; // Sola Doğru yüklenir. for (i=0;i<4;i++) // Satırlar dolduruluyor.. { spi_write(display_ram[j][row_adr]); j-=4; } k--; } output_high(LATCH); delay_cycles(2); output_low(LATCH); }
Bu Fonksiyonlar ile Yukarıdaki tablodaki ram alanı sürekli ekrana yansıtılır. Çalışması biraz karmaşık görünüyor ama öyle değil biraz inceleyip kodları adım adım takip ederseniz kolayca mantığını kavrarsınız.
Şimdi Yazıdığım Kütüphaneye bakalım. Kütüphanede Tüm Fonksiyonları ben yazmadım açıkçası. Temel olarak Daire çizme, Çizgi çizme, ve dikdörgen çizme fonksiyonlarını keilde ili9325 kütüphanemden aldım. Bunların yanı sıra PutPixel, GetPixel, Bargraph, clear_display, invert_display ve Text Basma Yazı Kaydırma gibi fonksiyonları ben hazırladım.
P10 CCS C Kütüphanesi
/******************************************************************************* * File Name : P10_Panel_Driver.c * Author : Ferhat YOL * Version : V1.0 * Date : 13/07/2013 * Description : P10 Panel kütüphanesidir. * : *******************************************************************************/ #include "font1 .h" #include "font2 .h" #include "font3 .h" #include "font4 .h" #define PinA pin_c0 #define PinB pin_c1 #define PinOE pin_c4 //OE=0 Display OFF, OE=1 Display ON #define LATCH pin_c6 #define Font1H 8 #define Font2H 12 #define Font3H 14 #define Font4H 16 #define Panel 1 //P10 Panel Sayısı #define RIGHT 0 // #define LEFT 1 // #define UP 2 // #define DOWN 3 // #define WIDTH 31 #define HEIGHT 15 unsigned int8 display_ram[16][4]; //Bu Bölge Display Ram Alanını belirtir unsigned char Text[50]=""; void clear_display (int1 fill); void invert_screen (void); void Set_Brightness (int8 value); void PutPixel (unsigned int Xpos, unsigned int Ypos, int1 fill); int1 GetPixel (unsigned int Xpos, unsigned int Ypos); void Line (unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int1 fill); void Rectangle (unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int1 fill); void Circle (unsigned int x, unsigned int y, unsigned int size, int1 fill); void Bargraph (unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int1 hor, unsigned int value); void ShowString (unsigned int x, unsigned int y, unsigned int size, int1 fill); void TextToLeftScroll (unsigned int Line, unsigned int Size, unsigned int speed, int1 fill); /******************************************************************************* * Satır Kaydırma Fonksiyonu * * Parameter: Line, ZeroBit * * Return: OwerFlow * *******************************************************************************/ int1 LineScroll(unsigned int Line, int1 ZeroBit){ unsigned int32 Tam=0; unsigned int y1=Line%4; unsigned int y2=Line/4; int1 OwerFlow; ZeroBit=1-Zerobit; OwerFlow=(display_ram[(y2*4)][y1]/128)&0x01; Tam=display_ram[(y2*4)][y1]; Tam=Tam< <8; Tam=Tam+display_ram[(y2*4)+1][y1]; Tam=Tam<<8; Tam=Tam+display_ram[(y2*4)+2][y1]; Tam=Tam<<8; Tam=Tam+display_ram[(y2*4)+3][y1]; Tam=Tam<<1; Tam=Tam+ZeroBit; display_ram[(y2*4) ][y1]=(int32)(Tam>>24)&0xFF; display_ram[(y2*4)+1][y1]=(int32)(Tam>>16)&0xFF; display_ram[(y2*4)+2][y1]=(int32)(Tam>>8)&0xFF; display_ram[(y2*4)+3][y1]=(int32)(Tam&0xFF); Return OwerFlow; } /******************************************************************************* * Text Basma Fonksiyonu Font1 * * Parameter: x, y, Fill * * Return: * *******************************************************************************/ void DrawCharFont1(unsigned x, unsigned y, int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int clm=x,row=y; While (Text[i]!='\0') { if(clm+5>WIDTH) //Satır sonuna gelindimi Bir Alt Satıra Geç { clm=0; row=row+8; if(row+8>HEIGHT+1) break; } for(b=0;b<5;b++) { cdata=Font_5x7[Text[i]-32][b]; for(a=0;a<8;a++) { PutPixel(clm+b,row+a,(fill-(cdata>>a) & 0x01)); } } i++; clm=clm+6; } } /******************************************************************************* * Text Basma Fonksiyonu Font2 * * Parameter: x, y, Fill * * Return: * *******************************************************************************/ void DrawCharFont2(unsigned int x, unsigned int y, int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int clm=x,row=y; while(Text[i]!='\0') { if(clm+8>WIDTH) //Satır sonuna gelindimi Bir Alt Satıra Geç { clm=0; row=row+12; if(row+12>HEIGHT+1) break; } for(b=0;b<16;b=b+2) { cdata=Font_8x12[Text[i]-32][b]; for(a=0;a<8;a++) { PutPixel(clm+(b/2),row+a,(fill-(cdata>>a) & 0x01)); } cdata=Font_8x12[Text[i]-32][b+1]; for(a=0;a<4;a++) { PutPixel(clm+(b/2),row+8+a,(fill-(cdata>>a) & 0x01)); } } clm=clm+8; i++; } } /******************************************************************************* * Text Basma Fonksiyonu Font3 * * Parameter: x, y, Fill * * Return: * *******************************************************************************/ void DrawCharFont3(unsigned int x, unsigned int y, int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int clm=x,row=y; while(Text[i]!='\0') { if(clm+12>WIDTH) //Satır sonuna gelindimi Bir Alt Satıra Geç { clm=0; row=row+14; if(row+14>HEIGHT+1) break; } for(b=0;b<24;b=b+2) { cdata=Font_12x14[Text[i]-32][b]; for(a=0;a<8;a++) { PutPixel(clm+(b/2),row+a,(fill-(cdata>>a) & 0x01)); } cdata=Font_12x14[Text[i]-32][b+1]; for(a=0;a<6;a++) { PutPixel(clm+(b/2),row+8+a,(fill-(cdata>>a) & 0x01)); } } clm=clm+12; i++; } } /******************************************************************************* * Text Basma Fonksiyonu Font4 * * Parameter: x, y, Fill * * Return: * *******************************************************************************/ void DrawCharFont4(unsigned int x, unsigned int y, int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int clm=x,row=y; while(Text[i]!='\0') { if(clm+12>WIDTH) //Satır sonuna gelindimi Bir Alt Satıra Geç { clm=0; row=row+16; if(row+16>HEIGHT+1) break; } for(b=0;b<24;b=b+2) { cdata=Font_12x16[Text[i]-32][b]; for(a=0;a<8;a++) { PutPixel(clm+(b/2),row+a,(fill-(cdata>>a) & 0x01)); } cdata=Font_12x16[Text[i]-32][b+1]; for(a=0;a<8;a++) { PutPixel(clm+(b/2),row+8+a,(fill-(cdata>>a) & 0x01)); } } clm=clm+12; i++; } } /******************************************************************************* * Text Kaydırma Fonksiyonu Font1 * * Parameter: Line, Speed, Fill * * Return: * *******************************************************************************/ void ScrollTextFont1 (unsigned int Line, unsigned int speed,int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int16 delay=speed*20; int1 ZeroBit=0; While(Text[i]!='\0') { if(Line+Font1H-1>HEIGHT)Break; for(b=0;b<5;b++) { cdata=Font_5x7[Text[i]-32][b]; for (a=0;a<8;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(Line+a,ZeroBit); } delay_Ms(210-delay); } for (a=0;a<8;a++) { LineScroll(Line+a,0); } delay_Ms(210-delay); i++; } } /******************************************************************************* * Text Kaydırma Fonksiyonu Font2 * * Parameter: Line, Speed, Fill * * Return: * *******************************************************************************/ void ScrollTextFont2(unsigned int Line, unsigned int Speed,int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int16 delay=speed*20; int1 ZeroBit=0; while(Text[i]!='\0') { if(Line+Font2H-1>HEIGHT)Break; for(b=0;b<16;b=b+2) { cdata=Font_8x12[Text[i]-32][b]; for(a=0;a<8;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(Line+a,ZeroBit); } cdata=Font_8x12[Text[i]-32][b+1]; for(a=0;a<4;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(Line+8+a,ZeroBit); } delay_Ms(210-delay); } i++; } } /******************************************************************************* * Text Kaydırma Fonksiyonu Font3 * * Parameter: Line, Speed, Fill * * Return: * *******************************************************************************/ void ScrollTextFont3(unsigned int Line, unsigned int Speed,int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int16 delay=speed*20; int1 ZeroBit=0; while(Text[i]!='\0') { if(Line+Font3H-1>HEIGHT)Break; for(b=0;b<24;b=b+2) { cdata=Font_12x14[Text[i]-32][b]; for(a=0;a<8;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(Line+a,ZeroBit); } cdata=Font_12x14[Text[i]-32][b+1]; for(a=0;a<6;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(Line+8+a,ZeroBit); } delay_Ms(210-delay); } i++; } } /******************************************************************************* * Text Kaydırma Fonksiyonu Font4 * * Parameter: Line, Speed, Fill * * Return: * *******************************************************************************/ void ScrollTextFont4(unsigned int Line, unsigned int Speed,int1 fill){ unsigned int a=0,b=0,i=0; unsigned int cdata=0; unsigned int16 delay=speed*20; int1 ZeroBit=0; while(Text[i]!='\0') { if(Line+Font4H-1>HEIGHT)Break; for(b=0;b<24;b=b+2) { cdata=Font_12x16[Text[i]-32][b]; for(a=0;a<8;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(a,ZeroBit); } cdata=Font_12x16[Text[i]-32][b+1]; for(a=0;a<8;a++) { ZeroBit=fill-(cdata>>a) & 0x01; LineScroll(8+a,ZeroBit); } delay_Ms(210-delay); } i++; } } /******************************************************************************* * Ekran Temizleme Fonksiyonu * * Parameter: fill * * Return: * *******************************************************************************/ void clear_display(int1 fill){ int8 i=0,j=0,fdata=0; if (fill){ fdata=0x00; }else{ fdata=0xFF; } for (i=0;i<4;i++) { for (j=0;j<16;j++) { display_ram[j][i]=fdata; } } } /******************************************************************************* * Ekran Tersleme Fonksiyonu * * Parameter: * * Return: * *******************************************************************************/ void invert_screen(void){ int8 i=0,j=0; for(i=0;i<4;i++) { for(j=0;j<16;j++) { display_ram[j][i] =~ display_ram[j][i]; //Önbellekteki değer değillenip geri yazılıyor } } } /******************************************************************************* * Parlaklık Ayar Fonksiyonu * * Parameter: value (0-100) * * Return: * *******************************************************************************/ void Set_Brightness(int8 value){ set_pwm1_duty((int16)value*10); } /******************************************************************************* * Pixel Fonksiyonu * * Parameter: Xpos, Ypos, fill * * Return: * *******************************************************************************/ void PutPixel(unsigned int Xpos,unsigned int Ypos, int1 fill) { int8 y1=0,x1=0; int8 y2=0,x2=0; int8 temp=0; y1 = Ypos%4; y2 = Ypos/4; x1 = Xpos%8; x2 = Xpos/8; if(fill) //Nokta Koy { temp=display_ram[(y2*4)+x2][y1]; //Ram'deki değer ön belleğe alınıyor. display_ram[(y2*4)+x2][y1] = (temp & (255-(128>>x1))); //x'inci bit 0 yapılır } else //Noktayı Sil { temp=display_ram[(y2*4)+x2][y1]; //Ram'deki değer ön belleğe alınıyor. display_ram[(y2*4)+x2][y1] = (temp | (128>>x1)); //x'inci Bit 1 yapılır } } /******************************************************************************* * Pixel Okuma Fonksiyonu * * Parameter: Xpos, Ypos * * Return: value * *******************************************************************************/ int1 GetPixel(unsigned int Xpos,unsigned int Ypos){ int8 y1=0,x1=0; int8 y2=0,x2=0; int8 temp=0; int1 value=0; y1 = Ypos%4; y2 = Ypos/4; x1 = Xpos%8; x2 = Xpos/8; temp=display_ram[(y2*4)+x2][y1]; //Ram'deki değer ön belleğe alınıyor. value=1-(0x80 & temp< <x1) 128;="" ram="" adresindeki="" bit="" geri="" gönderiliyor="" return="" value;="" }="" *******************************************************************************="" *="" Çizgi="" Çizme="" fonksiyonu="" parameter:="" x1,="" x2,="" y1,="" y2,="" fill="" return:="" void="" line(unsigned="" int="" unsigned="" int1="" fill)="" {="" signed="" int16="" addx="1," addy="1," p;="" i,="" dy,="" dx,="" diff;="" if(x2="">x1) { dx = x2 - x1; }else{ dx = x1 - x2; addx = -1; } if(y2>y1) { dy = y2 - y1; }else{ dy = y1 - y2; addy = -1; } if(dx >= dy) { dy *= 2; P = dy - dx; diff = P - dx; for(i=0; i< =dx; i++) { PutPixel(x1, y1, fill); if(P < 0) { P += dy; x1 += addx; } else { P += diff; x1 += addx; y1 += addy; } } } else { dx *= 2; P = dx - dy; diff = P - dy; for(i=0; i<=dy; ++i) { PutPixel(x1, y1, fill); if(P < 0) { P += dx; y1 += addy; } else { P += diff; x1 += addx; y1 += addy; } } } } /******************************************************************************* * Dikdörtgen Çizme Fonksiyonu * * Parameter: x1, x2, y1, y2, fill * * Return: * *******************************************************************************/ void Rectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int1 fill) { unsigned int16 i, xmin, xmax, ymin, ymax; if(fill) { if(x1 < x2) { xmin = x1; xmax = x2; } else { xmin = x2; xmax = x1; } if(y1 < y2) { ymin = y1; ymax = y2; } else { ymin = y2; ymax = y1; } for(; xmin <= xmax; ++xmin) { for(i=ymin; i<=ymax; ++i) { PutPixel(xmin, i, 1); } } } else { Line(x1, y1, x2, y1, 1); Line(x2, y1, x2, y2, 1); Line(x2, y2, x1, y2, 1); Line(x1, y2, x1, y1, 1); } } /******************************************************************************* * Çember Cizme Fonksiyonu * * Parameter: x, y, Size, fill * * Return: * *******************************************************************************/ void Circle(unsigned int x, unsigned int y, unsigned int size, int1 fill) { signed int a,b,P; a=0; b=size; P=1-size; do { if(fill) { Line(x-a, y+b, x+a, y+b,1); Line(x-a, y-b, x+a, y-b,1); Line(x-b, y+a, x+b, y+a,1); Line(x-b, y-a, x+b, y-a,1); } else { PutPixel(a+x, b+y,1); PutPixel(b+x, a+y,1); PutPixel(x-a, b+y,1); PutPixel(x-b, a+y,1); PutPixel(b+x, y-a,1); PutPixel(a+x, y-b,1); PutPixel(x-a, y-b,1); PutPixel(x-b, y-a,1); } if(P < 0) P+= 3 + 2*a++; else P+= 5 + 2*(a++ - b--); }while(a<=b); } /******************************************************************************* * Bargraph Çizme Fonksiyonu * * Parameter: x1, y1, x2, y2, Mode, Value * * Return: * *******************************************************************************/ void Bargraph (unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int1 hor, unsigned int value,) { unsigned int w=0; unsigned int h=0; unsigned int a=0,b=0; unsigned int16 barval=0; if(x1>x2) w=x1-x2; if(x1y2) h=y1-y2; if(y1 if(hor) //Bar Yatay Olarak Oluşturulacak { barval=((int16)value*h)/100; for (a=0;a<h+1;a++) { for(b=0;b<w+1;b++) {="" if(barval="">=a){ PutPixel(x1+b,15-a+y1,1); }else{ PutPixel(x1+b,15-a+y1,0); } } } }else{ //Bar Dikey olarak Oluşturulacak barval=((int16)value*w)/100; for (a=0;a { for(b=0;b<h+1;b++) {="" if(barval="">=a) { PutPixel(x1+a,y1+b,1); }else{ PutPixel(x1+a,y1+b,0); } } } } } /******************************************************************************* * Text Basma Fonksiyonu * * Parameter: x, y, size, fill * * Return: * *******************************************************************************/ void ShowString(unsigned int x, unsigned int y, unsigned int size, int1 fill){ switch(size) { case 1: DrawCharFont1(x,y,fill);break; case 2: DrawCharFont2(x,y,fill);break; case 3: DrawCharFont3(x,y,fill);break; case 4: DrawCharFont4(x,y,fill);break; default: break; } } /******************************************************************************* * Text Kaydırma Fonksiyonu * * Parameter: Line, Size, Speed, Fill * * Return: * *******************************************************************************/ void TextToLeftScroll(unsigned int Line, unsigned int Size, unsigned int Speed,int1 fill){ switch (size) { case 1: ScrollTextFont1(Line,Speed,fill);Break; case 2: ScrollTextFont2(Line,Speed,fill);Break; case 3: ScrollTextFont3(Line,Speed,fill);Break; case 4: ScrollTextFont4(Line,Speed,fill);Break; default: Break; } }
Kütüphanenin kullanımı çok basit. PutPixel, GetPixel, Line, Rectangle, Circle, Gibi fonksiyonları TFT ekranlarda olduğu gibi kullanabilirsiniz. Sadece Text Basma ve Yazı kaydırma gibi kendi hazırladığım fonksiyonlarına değinmek istiyorum.
Bu fonksiyonları hazırlarken Basılacak veya kaydırılacak olan Text’i fonksiyonun içeriğine göndermeye çalıştım. Bunun için ccs c de göstericilerden faydalanmak gerekiyor. Epeyce bir uğraşmama rağmen gösterici kullanarak yapamadım.
Bende TEXT için ayrı bir ram alanı ayırdım. Yazılacak veya kaydırılacak stringi bu ram alanına yazmak gerekiyor. Ardından yazı basılacaksa text basma fonksiyonunu, kaydırma işlemi yapılacaksa yazı kaydırma fonksiyonunu çağırmak gerekiyor.
Örnek vermek gerekirse,
Text=”ABCDEFGH”;
ShowString(Xpos,Ypos,Size, Fill);
Bu fonksiyon verilen koordinatlara Text Basar. Xpos ve Ypos Parametreleri koordinat bilgisidir.
Size Parametresi ise Font Seçim Parametresidir. Benim Programa gömdüğüm 4 dahili font var. Bu yüzden Size Parametresine 1 ile 4 arası bir değer vermeniz gerekir.
Font demişken 2. Ve 3. Fontlarla fazla ilgilenemedim. Biraz düzenlenmesi gerekebilir.
Fill Parametresi Yazının invert olarak basılıp basılmayacağının ayarlandığı parametredir. 1 gönderirseniz yazıyı tersleyip basar. 0 gönderirseniz normal olarak basar.
TextToLeftScroll(Line, Size, Speed, fill);
Bu fonksiyon verilen satırdan itibaren Text Kaydırmaya başlar. Yazının tamamı kayıp bitene kadar fonksiyondan çıkamaz işlemci. Bu fonksiyonun en kötü tarafıda bu oldu.
Neyse Parametrelere gelince
Line; Satır seçim parametresidir. Kaçıncı satırdan itibaren yazı kaydırılacağını belirtir.
Size; Text Basma Fonksiyonunda olduğu gibi font seçim paramteresidir.
Speed; Yazı Hızı Parametresi, 1 ile 10 arası değer alır.
Fill; Text Basma Fonksiyonundaki ile aynı işi görür.
Text Basma iyi çalışıyor fakat yazı kaydırma benim pek aklıma yatmadı. Sistemde Rtos benzeri bir yapı olmadığı için Kaydırılacak yazının tümü bitene kadar program yazı kaydırma fonksiyonundan çıkamıyor. Kesme kullanarak bu halledilebilir fakat program esnek olmazdı.
Birde Bargraph üzerine Değineyim.
Bargraph oluşturma fonksiyonunuda ben yazdım. Kullanımı şu şekilde
Bargraph (unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int1 hor, unsigned int value);
x1, y1, x2 ve y2 parametreleri ile bargraph boyutu belirlenir.
hor; Bu parametre Bar’ın yataymı yoksa dikeymi çalışacağını belirtir.
Value: Değeri ise Barın değeridir. 0-100 arası bir değer alır.
Bargraph üzerine örnek demo programda bulunmaktadır.
Son olarak Parlaklık ayarı üzerine değinmek istiyorum.
Displayin parlaklığını ayarlamak için Donanımsal pwm modülünü kullandım. Pwm Frekansını 10Khz ye ayarladıktan sonra işlemciden çıkan OE sinyaliyle üst üste bindirmek gerekiyor. Bunun için ben bir adet 7408 enteğresini kullandım. 7408 VE kapısının girişlerinin birine pwm sinyali diğerinede OE sinyalini verdikten sonra 7408 in çıkışını Panelin OE kontrol pinine bağladım. Sonra PWM sinyalinin duty cycle değeriyle oynayarak parlaklığı Ayarladım. Ben bu şekilde yaptım. Diğer sürücü kartları nasıl yapıyor açıkçası hiç bilmiyorum.
Örnek bir Test programı hazırladım. Bu test programında kütüphanenin bütün özelliklerini göstermeye çalıştım
#include <18F4620.h> #device adc=10 #FUSES NOWDT //No Watch Dog Timer #FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale #FUSES H4 //High speed osc with HW enabled 4X PLL #FUSES NOBROWNOUT //No brownout reset #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode) #use delay(clock=40000000) #use fast_io(a) #use fast_io(b) #use fast_io(c) #use fast_io(d) #use fast_io(e) #include <math.h> /*******************************P10 Panel kütüphanesi**************************/ #include <P10_Panel_Driver.c> /********************************Global Değişkenler****************************/ unsigned int8 int_syc=0; int i=0,w=0; /**********************************Fonksiyonlar********************************/ void write_data (unsigned int8 row_adr); void FontTest (void); void NumberTest (void); void ScrollTest (void); void BrightTest (void); void GeoShapes (void); void SineWawe (void); void BarTest (void); /********************************Kesme Alt Programı****************************/ #int_timer0 //Timer0 Kesmesi void Timer0_int(){ set_timer0(133); //800us Gecikme için Timer kuruluyor.. switch (int_syc) //Her 800us de Bir bir sonraki satıra Geç { case 0: output_low(PinOE);write_data(int_syc); output_low(PinA);output_low(PinB);output_high(PinOE); break; case 1: output_low(PinOE);write_data(int_syc); output_high(PinA);output_low(PinB);output_high(PinOE); break; case 2: output_low(PinOE);write_data(int_syc); output_low(PinA);output_high(PinB);output_high(PinOE); break; case 3: output_low(PinOE);write_data(int_syc); output_high(PinA);output_high(PinB);output_high(PinOE); break; } int_syc++;if(int_syc>3)int_syc=0; } /**********************************Ana Program*********************************/ void main() { set_tris_a(0x03); set_tris_b(0x00); set_tris_c(0x00); set_tris_d(0x00); set_tris_e(0x00); setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_SS_DISABLED); setup_adc(ADC_OFF); setup_ccp1(CCP_PWM); setup_ccp2(CCP_OFF); setup_timer_0(T0_INTERNAl | T0_8_BIT | T0_DIV_64); setup_timer_2(T2_DIV_BY_4,249,1); enable_interrupts(INT_timer0); enable_interrupts(GLOBAL); set_timer0(133); output_a(0x00); output_b(0x00); output_c(0x00); output_d(0x00); output_e(0x00); Set_Brightness(10); //Parlaklık veriliyor. clear_display(0); //Ekranı Temizle Text="P10"; ShowString(7,0,1,0); Text="Test"; ShowString(4,8,1,0); delay_ms(1500); for (i=0;i<32;i++) { for (w=0;w<16;w++) { LineScroll(w,0); } delay_ms(30); } while(TRUE) { FontTest(); delay_ms(1000); NumberTest(); delay_ms(1000); ScrollTest(); delay_ms(1000); BrightTest(); delay_ms(1000); GeoShapes(); delay_ms(1000); SineWawe(); delay_ms(1000); BarTest(); delay_ms(2000); Text="www.arectron.com "; TextToLeftScroll(4,1,9,0); delay_ms(2000); } } void write_data(unsigned int8 row_adr) { int8 i=0,j=0; int8 k=3; while(k!=255) // Bu Döngü ileriye doğru sayarsa panel sağdan {j=15-k; // Sola Doğru yüklenir. for (i=0;i<4;i++) // Satırlar dolduruluyor.. { spi_write(display_ram[j][row_adr]); j-=4; } k--; } output_high(LATCH); delay_cycles(2); output_low(LATCH); } void FontTest(void){ Text="Font"; ShowString(3,0,1,0); Text="Test"; ShowString(3,8,1,0); delay_ms(1500); clear_display(0); delay_ms(100); Text="A"; for (i=1;i<5;i++) { ShowString(0,0,i,0); delay_ms(400); clear_display(0); } Text="B"; for (i=1;i<5;i++) { ShowString(0,0,i,0); delay_ms(400); clear_display(0); } Text="C"; for (i=1;i<5;i++) { ShowString(0,0,i,0); delay_ms(400); clear_display(0); } Text="D"; for (i=1;i<5;i++) { ShowString(0,0,i,0); delay_ms(400); clear_display(0); } } void NumberTest(void){ Text="Numbr"; ShowString(0,0,1,0); Text="Test"; ShowString(0,8,1,0); delay_ms(1000); clear_display(0); delay_ms(100); for (i=0;i<100;i++) { sprintf(Text,"%02d",i); ShowString(4,0,4,0); delay_ms(100); } for (i=0;i<3;i++) { Text="--";// ShowString(4,0,4,0); delay_ms(700); clear_display(0); delay_ms(500); } clear_display(0); Text="iNVRT"; ShowString(0,4,1,0); delay_ms(1000); clear_display(1); delay_ms(100); for (i=0;i<100;i++) { sprintf(Text,"%02d",i); ShowString(4,0,4,1); delay_ms(100); } for (i=0;i<3;i++) { Text="--";// ShowString(4,0,4,1); delay_ms(700); clear_display(1); delay_ms(500); } delay_ms(500); for (i=0;i<32;i++) { for (w=0;w<16;w++) { LineScroll(w,0); } delay_ms(15); } } void ScrollTest(void){ Text="Scrol"; ShowString(0,0,1,0); Text="Test"; ShowString(0,8,1,0); delay_ms(1000); clear_display(0); delay_ms(100); Text="FONT 1 "; TextToLeftScroll(0,1,9,0); delay_ms(800); Text="FONT 2 "; TextToLeftScroll(0,2,9,0); delay_ms(700); Text="FONT 3 "; TextToLeftScroll(0,3,9,0); delay_ms(600); Text="FONT 4 "; TextToLeftScroll(0,4,9,0); delay_ms(500); clear_display(1); Text="Hardware Pic18F4620 & 40Mhz, 64Kb Flash, 3968Byte Ram vs.. "; TextToLeftScroll(0,4,9,1); clear_display(0); } void BrightTest(void) { for(i=1;i<100;i++) { Text="Brigt"; ShowString(0,0,1,0); sprintf(Text,"%02d",i); ShowString(10,8,1,0); Set_Brightness(i); delay_ms(150); } Set_Brightness(100); clear_display(0); Text="MAX"; for(i=0;i<4;i++) { ShowString(4,3,2,0); delay_ms(800); clear_display(0); delay_ms(500); } Set_Brightness(10); } void GeoShapes(void){ Rectangle(14,6,17,9,0); delay_ms(600); clear_display(0); Rectangle(11,3,20,12,0); delay_ms(600); clear_display(0); Rectangle(8,0,23,15,0); delay_ms(600); clear_display(0); Rectangle(14,6,17,9,1); delay_ms(600); clear_display(0); Rectangle(11,3,20,12,1); delay_ms(600); clear_display(0); Rectangle(8,0,23,15,1); delay_ms(1000); clear_display(0); Circle(16,8,2,0); delay_ms(600); clear_display(0); Circle(16,8,4,0); delay_ms(600); clear_display(0); Circle(16,8,7,0); delay_ms(600); clear_display(0); Circle(16,8,2,1); delay_ms(600); clear_display(0); Circle(16,8,4,1); delay_ms(600); clear_display(0); Circle(16,8,7,1); delay_ms(1000); clear_display(0); delay_ms(100); Line(0,0,31,15,1); delay_ms(600); Line(0,15,31,0,1); delay_ms(600); Line(5,0,8,15,1); delay_ms(600); Line(31,8,0,4,1); delay_ms(600); Line(29,0,10,15,1); delay_ms(600); Line(31,13,0,8,1); delay_ms(1000); clear_display(0); } void SineWawe(void){ float ax=0; int16 xpos=0; int8 ypos=0,sayac=0; Text="Sine"; ShowString(0,0,1,0); Text="Wave"; ShowString(0,8,1,0); delay_ms(1000); clear_display(0); delay_ms(100); while(True) { for(xpos=0;xpos<19;xpos++) { for (i=0;i<16;i++){ LineScroll(i,0); } ax=(pi*xpos)/180; ypos=8+(7*sin(19*ax)); PutPixel(31,ypos,1); delay_ms(30); } sayac++;if(sayac==10)break; } clear_display(0); } void BarTest(void){ int xstart=0,xend=3; Text="Bar"; ShowString(0,0,1,0); Text="Test"; ShowString(0,8,1,0); delay_ms(1000); clear_display(0); delay_ms(100); for(w=0;w<8;w++) { for(i=0;i<101;i++) { Bargraph(xstart,0,xend-1,15,1,i); delay_ms(2); } xstart=xstart+4;xend=xend+4; } xstart=0;xend=3; for(w=0;w<8;w++) { for(i=0;i<101;i++) { Bargraph(xstart,0,xend-1,15,1,100-i); delay_ms(2); } xstart=xstart+4;xend=xend+4; } clear_display(0); xstart=0;xend=3; for (w=0;w<4;w++) { for (i=0;i<101;i++) { Bargraph(0,xstart,31,xend-1,0,i); delay_ms(2); } xstart=xstart+4;xend=xend+4; } xstart=0;xend=3; for (w=0;w<4;w++) { for (i=0;i<101;i++) { Bargraph(0,xstart,31,xend-1,0,100-i); delay_ms(2); } xstart=xstart+4;xend=xend+4; } clear_display(0); for(w=0;w<2;w++) { for(i=0;i<101;i++) { Bargraph(0,0,31,15,1,i); delay_ms(1); } for(i=0;i<101;i++) { Bargraph(0,0,31,15,1,100-i); delay_ms(1); } } clear_display(0); for(w=0;w<2;w++) { for(i=0;i<101;i++) { Bargraph(0,0,31,15,0,i); delay_ms(1); } for(i=0;i<101;i++) { Bargraph(0,0,31,15,0,100-i); delay_ms(1); } clear_display(0); } }
Bu hazırladığım kütüphane 1 panele göre ayarlanmış durumda. Panel sayısını arttırırsanız fonksiyonlarıda yeniden ayarlamanız gerekecektir. En önemlisi Ram alanını arttırmanız gerekir. Örneğin iki panel için 32×4 lük bir dizi kullanmanız gerekecektir. Buna benzer ayarları diğer fonksiyonlar içinde yapmanız gerekir.
Yukarıdaki Test Programının çalışma videosunu çektim.
Diyeceklerim bu kadar.
Bir sonraki yazımda görüşmek dileğiyle.
P10 Led Panel CCS C Uygulama kod dosyaları;
Şifre-Pass: 320volt.com
Yayım tarihi: 2013/08/23 Etiketler: microchip pic projeleri, p10 led ccs c, p10 led circuit, p10 led panel, PIC18F4620, pic18f4620 ccs c
elinize emeğinize sağlık
Çözümler mantıklı,güzel ve ara konulara geçişlerdeki ek açıklamalar da tatmin edici olmuş,elinize sağlık..
çinlilerden aldığım p10 led tabelaların pcb ve şeması ve birçok şeyi bulabileceginiz bir dosya arşivi.
http://www.4shared.com/rar/e0IJE-MT/LED_T-_—_.html
güle güle kullanın
Merhaba
Devreyi yaptım fakat programlayıcım 18f4620’i desteklemediği için 18f452 kullandım. çalıştı fakat fontlarda problem var gibi .bazı pixeller arada yanık kalıyor.
18f4620 programlayıcı temin edip tekrar deneyeceğim
problem ile ilgili başka bir öngörünüz var mı.?
Teşekkürler..
Merhaba
D128 USB programlayıcımı güncelleyince 18f4620 yi programlayabildim.Şimdi gayet güzel çalışıyor.
Teşekkürler..
teşekkürler güzel bir çalışma olmuş..yanlız 9. 17. 25. sütundaki ledler farklı sütunlarda yanıyor sebebi ne olabilir acaba
nazım bey mikrodenetleyiciyi değiştirince mi sorun düzeldi.bende de aynı durum oluştu da..
elinize sağlık ben yazılımı hex haline çeviremedim yazılımda bir eksiklikmi var.
şimdiden teşekkürler
Merhaba ben ornek programı kullanıb baska yazılar yazmak istiyorum ama,yazdigim programi derlediyimde CCS PIC18f4620 kutuphanedi ve LEDP10 kutuphanesi ile ilgili hata verior,sorun nerden ola bilir yardimci olursaniz cok sevinirim.
saat ve tarih eklemek istiyorum yardımcı olursanız çok sevinirim iyi çalışmalar
Güzel çalışma tebrikler.
Merhaba. Ben 18f2550 entegresiyle yapmaya çalıştım olmadı. Yardımcı olabilir misiniz?
Acaba bu işlemi P5 RGB paneller üzerinde de yapabilir miyiz?