Ana Sayfa PIC Assembly - PIC C PIC16F877 ile MCP3204 Harici ADC Uygulaması(SPI Protokolü, Grafik LCD Kullanımı)

PIC16F877 ile MCP3204 Harici ADC Uygulaması(SPI Protokolü, Grafik LCD Kullanımı)

39 min read
0
0
919

Merhabalar arkadaşlar. Roboturka ailesi olarak bugün harici RAM, EEPROM, ADC gibi bir çok alanda kullanılan SPI haberleşmesi üzerine bir inceleme yapacağız. SPI haberleşmesi ile harici ADC kullanımını göreceğiz. ADC’den aldığımız bilgileri grafik LCD’de görüntüleyeceğiz. SPI haberleşmesi ve grafik LCD kullanımı hakkında bilgi vermek ve sizleri fikir sahibi yapmayı amaçlıyoruz. Çalışmamız ile ilgili videoya göz atabilirsiniz:

Proje Dosyaları

Elemanlar:
-PIC 16F877 Mikrodenetleyici
-MCP3204 Harici ADC Entegresi
-Grafik LCD (KS0108 Tipi)
-Buton (3 Adet)
-Direnç(3 x 10K Ohm, 3 x 330 Ohm)
-Gerekli Devre Elemanları(Board, Jumper vs…)

Elemanlarımızı tanıdıktan sonra projemize geçebiliriz. Projemizde kullandığımız SPI haberleşmesini ve MCP3204 harici ADC entegresini tanıyalım:

SPI Haberleşme Protokolü

Serial Peripheral Interface Bus ya da SPI veri yolu full duplex modda çalışan senkron bir seri veri bağlantısı standardıdır. İlk olarak Motorola tarafından bulunup, kullanılmıştır. Dört pinli bağlantıdan oluşan, seri bir haberleşmedir. SPI iletişimindeki iki elemana “master(efendi, usta)” ve “slave(köle, çırak)” adları verilir. Genel olarak düşünecek olursak master(efendi) eleman talimat veren, konfigüre eden eleman; slave(köle) eleman ise konfigüre edilip, aldığı talimatlara göre bir çıkış veren eleman olarak düşünülebilir. SPI iletişimdeki dört pini tanıyalım:

Clk (Clock-SCLK): Clock sinyalinin sağlandığı pindir. Master(efendi) eleman tarafından slave(köle) eleman ile haberleşebilmek üzere oluşturulan clock sinyalinin uygulandığı giriştir. Veri alış-verişi her bir clock sinyali ile gerçekleşir.

MOSI (Master Output, Slave Input): Master(efendi) elemanın çıkışı, slave(köle) elemanın girişidir. Slave(köle) elemanı gerekli şekilde konfigüre edebilmek için kullanılır, slave(köle) elemana bilgi gönderilir. Her bilgi clock sinyali ile gönderilir.

MISO (Master Input, Slave Output): Master(efendi) elemanın girişi, slave(köle) elemanın çıkışıdır. Gerekli konfigürasyon işlemlerinden sonra slave(köle) elemandan master(efendi) elemana bilgi aktarımı sağlanır. Bilgi aktarımı clock sinyali ile gerçekleşir.

SS (Slave Select-CS-CS/SHDN): Slave(köle) eleman seçmek için kullanılır. SS pini “0” yapıldığı zaman slave(köle) eleman seçilmiş, haberleşmeye hazır haldedir.

SPI Haberleşme Pinleri

Pinleri genel manasıyla tanıdıktan sonra SPI iletişimi genel olarak anlatalım: SPI iletişimde genel olarak öncelikle SS pini lojik-1 seviyesinde tutularak slave(köle) eleman haberleşmeye kapalı halde tutulur. Haberleşmenin başlaması için SS pini lojik-0’a getirilir. Bundan sonra master(efendi) eleman tarafından clock sinyali üretilerek haberleşme başlar. Bu sırada clock sinyaliyle birlikte MOSI pininin lojik durumuna göre slave(köle) elemanına her clock sinyali ile “1” veya “0” bilgisi gönderilerek slave(köle) eleman konfigüre edilir. O anda MOSI pini hangi lojik durumdaysa slave(köle) elemana o lojik durum gönderilir. Konfigürasyon işleminden sonra slave(köle) eleman MISO pini ile master(efendi) elemana her clock sinyaliyle bir bitlik bilgi gönderir. MISO’dan gerekli bilgi alındıktan sonra clock sinyali kesilip, SS pini lojik-1 yapılarak haberleşme bitirilebilir.

SPI Seri Haberleşmesi

Genel olarak SPI haberleşmesini yukarıda anlattık. SPI haberleşmesini doğru yapabilmek için zamanlamalara uymak gerekir. Örneğin; kimi elemanların maksimum clock frekansı 10 MHz iken, kimi elemanlarda bu değer 2 MHz olabilir. Her eleman için aynı zamanlama kullanılmamalıdır, datasheet’teki veriler dikkatlice incelenmelidir. Veri alış-verişinde clock sinyalinin hangi durumunun kullanıldığı da önemlidir. Clock sinyalinin lojik-1 olduğu durumda veri gönderilirken, veri alımı clock sinyalinin düşen kenarı ile yapılır. Bunlara dikkat etmeli, datasheet okurken sıkılmamalıyız :). Ayrıca slave(köle) elemanı doğru konfigüre edebilmek de önemlidir. Doğru konfigüre edemediğimiz elemandan doğru bilgi bekleyemeyiz.

Yukarıda genel olarak SPI iletişimden bahsettik. Artık bir çok mikrodenetleyicide donanımsal SPI birimi bulunmaktadır ve işleri daha da kolaylaştırmaktadır. Hazır fonksiyonlar gerekli şekilde yapılandırılarak SPI iletişim sağlanmaktadır. Fakat her mikrodenetleyicide kullanılabilmesi ve iletişimin mantığının daha iyi kavranması için örneğimizde SPI iletişimi yazılımsal olarak kullanılmıştır.

SPI iletişim hakkında bilgi sahibi olduktan sonra entegremizi tanıyalım:

MCP3204 Harici ADC Entegresi
MCP3204 entegresi Microchip firması tarafından üretilen, 12-bit hassasiyette, 4 kanal bir analog-dijital dönüştürücüdür. MCP3204, SPI seri haberleşmesini kullanır. Tekli modda veya fark modunda çalışabilir.

MCP3204 Pin Bağlantısı

MCP3204 pin bağlantısı yukarıda görülmektedir. SPI haberleşmesinde kullanılan pinler Din, Dout, CLK ve CS/SHDN pinleridir. Entegreyle alakalı detaylı teknik bilgi almak için datasheete buradan ulaşabilirsiniz.

Şimdi entegreyle haberleşmenin nasıl yapıldığını inceleyelim. Daha önce de söylediğimiz gibi MCP3204 ile SPI protokolünü kullanarak haberleşeceğiz. SPI protokolünü bir önceki bölümde inceledeik. MCP3204 ile haberleşmeye başlamak için CS/SHDN pini ilk önce lojik-1 durumunda olmalıdır(SHDN durumu). Daha sonra CS/SHDN lojik-0 yapılır ve ADC haberleşmeye hazır olur. Gerekli bekleme süresinden sonra, ADC’ye clock sinyali verilebilir. Gerekli bekleme süresi derken aklınıza fazla süreler gelmesin. Bu süreler genellikle mikrosaniyelerle, hatta nanosaniyelerle ifade edilir. SPI iletişimi tam anlamıyla kavramak açısından belirtiyorum. Açıklamamızı yaptıktan sonra devam edebiliriz. Bekleme süresinden sonra clock sinyali ile ADC’ye Din pininin lojik durumuna göre “0” veya “1” bilgisi gönderilir. İlk clock sinyali ile gönderilen bilgi “Start” bitidir, haberleşmenin devam etmesi için bu bit “1” şeklinde gönderilmelidir. Daha sonra göndereceğimiz bit Single/Different bilgisidir. Single tek kanal okuma modu, different ise kanallar arası fark modudur. Single için “1”, different için “0” gönderilir. Single/different seçiminden sonra hangi kanalın okunacağı seçilir. Bir sonraki üç clock sinyali ile D2, D1 ve D0 bilgisi ADC’ye gönderilir. D2, MCP3204 için önemsizdir(Don’t Care). MCP3204 konfigürasyon tablosu aşağıda görülmektedir, tabloya bakılarak istenilen kanal seçilebilir:

MCP3204 Konfigürasyon Tablosu

MCP3204 Konfigürasyon Tablosu

Bütün talimatlar gönderildikten sonra artık bilgi okumaya başlayabiliriz. Entegreye D0 bitini gönderdikten sonraki ilk clock sinyali ile ADC “Null Bit” gönderir. Bu biti okumaya dahil etmemeliyiz. Null bit’ten sonraki 12 clock sinyali ile ADC’den değer okunur. Burada dikkat edilmesi gereken bir şey var. Okunacak olan değer clock sinyalinin düşen kenarı ile Dout pininden okunur ve okuma en yüksek değerlikli bitten(MSB-Most Significant Bit) başlanarak yapılır. Daha sonra clock sinyali durdurulur, CS/SHDN pini lojik-1 yapılır ve haberleşme bitirilir. MCP3204 entegresi ile haberleşme bu şekilde yapılmaktadır. Hatırlatmakta fayda var: entegreye bilgi gönderilirken clock sinyalinin lojik-1 olduğu durumda Din pininden, bilgi okunacağı zaman clock sinyalinin düşen kenarı ile Dout pininden okuma-yazma işlemi yapılır. Haberleşmeyle alakalı dikkat edilecek bir diğer husus ise zamanlamadır. Bu sorunu da datasheet’teki zamanlama tablosuna bakarak kolayca aşabiliriz:

MCP3204 Zamanlama Tablosu

MCP3204 Zamanlama Tablosu

Yukarıdaki zamanlama tablosunda belirli zamanların minimum ve maksimum değerleri verilmiştir. Haberleşmeyi yaparken bu değerlere dikkat etmemiz gerekir.

Grafik LCD

Grafik LCD, karakter LCD’den farklı olarak her pikseli üzerinde ayrı ayrı işlem yapmamıza olanak tanır. Piksellere ne kadar iyi hükmedebildiğimize bağlı olarak kullanıcıya anlaşılır grafikler sunabiliriz. Bu nedenle “grafik” ismi verilmiştir. Örneğimizde çok popüler olan KS0108 tipi grafik LCD kullandık. Grafik LCD kodları program kodlarında incelenmiştir. Grafik LCD pin bağlantısını inceleyelim:

Grafik LCD Pin Bağlantısı

Program

Gerekli dökümanları ve elemanları inceledikten sonra kodlara geçebiliriz. Kodlar aşağıda açıklamalarıyla birlikte verilmiştir. Daha iyi inceleme yapmak için derleyicinize yapıştırıp gözatmanızı öneririz:


#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=20000000)
//*********************
#include <HDM64GS12.c>
#include <graphics.c>
#include <stdlib.h>
//**********************
//*********************
#define clk PIN_A0
#define din PIN_A1
#define dout PIN_A2
#define cs PIN_A3
#define asagi PIN_E0
#define yukari PIN_E1
#define sec PIN_E2
#define t 1 //Chip Select=0 olduktan sonraki bekleme süresi.
#define sure 1 //Clk sinyali süresi.
//**********************
//*******************************************************
int1 cursor=0; //1 bitlik değişken. Sadece 0-1 değerlerini alır.
int i,j,z,sayac=0,select,cursor_2=0,k[4],sd=1,data2=0,data1=0,data0=0;
int32 volt_int[3];
char string[13],y[13],str_float[4];
//********************************************************
//************************************************************
char diff[]={'D','i','f','f','e','r','e','n','t',0};
char single[]={'S','i','n','g','l','e',0};
char mod[]={'M','o','d',':',0},baslik[]={'M','C','P',' ','H','a','r','i','c','i',' ','A','D','C',0};
char ch3[]={'C''H''3',0},ch2[]={'C','H','2',0},ch1[]={'C''H''1',0},ch0[]={'C''H''0',0},kanal[]={'K''a''n''a''l'':',0};
char ch0_1[]={'C','H','0','-','C','H','1',0},ch1_0[]={'C','H','1','-','C','H','0',0},ch2_3[]={'C','H','2','-','C','H','3',0},ch3_2[]={'C','H','3','-','C','H','2',0};
char uyari[]={'R''e''s''t''a''r''t'':''3'' ''x'' ''S''e''c',0};
//**********************************************************************************
//********************************************
void MCP3204_init() {
//Haberleşmeyi başlat:
output_high(cs);
delay_us(t);
output_low(cs);
delay_us(t);
}int16 MCP3204(int1 singdiff,d2,d1,d0) { //ADC'ye bu 4 bitlik bilgi gönderilir.
//singdiff: Tekli(Single) okuma veya fark(Different) okuma modunu etkileyen bittir.
//d2: Don't care, değeri önemsizdir.
//d1 ve d0: Hangi kanalın okunacağını seçen bilgiyi taşırlar.
//Ayrıntılı bilgi datasheet'te yer almaktadır.
//*****************************************************************************
//ADC'ye talimat verilirken clock sinyali "1" durumunda olmalıdır.
//ADC'den bilgi okurken clock sinyalinin düşen kenarı ile ADC bize bilgi yollar.
//Haberleşmede buna dikkat etmek gerekir.
int16 deger;//Start biti gönder:
output_high(din); //ADC'nin girişi( Din) "1" yapılıyor. Daha sonra clock sinyali "1" yapılıyor.
output_high(clk); //Böylece clock sinyali "1" durumundayken ADC'nin girişi(Din) "1" durumunda olur ve "1" bilgisi aktarılır.
delay_us(sure); //sure boyunca clock sinyali "1" durumunda tutulur. Datasheet'e bakılarak clock sinyalinin hangi aralıkta olması gerektiği öğrenilebilir.
output_low(clk); //Burada clock sinyali 1 us "high" 1 us "low" durumunda tutulmaktadır, uygulama için yeterlidir.
output_low(din);
delay_us(sure);
//Start bitinden sonra kullanıcının menüden seçtiği kanala göre değer alan singdiff, d1 ve d0 bitleri ADC'ye gönderilir.
//Varsayılan(default) olarak singdiff=1(Single-Tekli okuma), D1=0, D0=0(CH1-1. kanal) değerleri belirlenmiştir.
//Kullanıcının girişine göre Single/Diff, D2, D1, D0 bitleri:
output_bit(din,singdiff); //Single/Diff biti.
output_high(clk);
delay_us(sure);
output_low(clk);
delay_us(sure);
output_bit(din,d2); //D2 biti.(Dont Care)
output_high(clk);
delay_us(sure);
output_low(clk);
delay_us(sure);
output_bit(din,D1); //D1 biti.
output_high(clk);
delay_us(sure);
output_low(clk);
delay_us(sure);
output_bit(din,D0); //D0 biti.
output_high(clk);
delay_us(sure);
output_low(clk);
delay_us(sure);
//Talimatlar tamamlandı. Şimdi ADC verdiğimiz talimatlara göre bize bilgi gönderecek.
//Datasheet'te yazdığı üzere, ADC bilgi göndermeden önce bir adet "null bit" gönderir. Bu biti önemsememeliyiz.
//Bilgi alma işlemi:
output_high(clk); //Null bit alındı.
delay_us(sure);
output_low(clk);
delay_us(sure);
//Şimdi clk sinyalinin düşen kenarı ile bilgi alınacak.
//ADC bilgi göndermeye MSB'den(most significant bit - en yüksek değerlikli bit) başlar.
//Clk sinyalinin düşen kenarı ile MSB'den başlayarak bilgi alınır:
for (i=0;i<=11;i++) {
output_high(clk);
delay_us(sure);
output_low(clk);
//Clk sinyalinin düşen kenarı ile bilgi alınacağı için clk "low" yapıldıktan sonra değişkene değer atanır:
if (input(dout)) { //ADC çıkışı(Dout) 1 ise "deger" değişkeninin 11. bitine 1 değeri atanır.
bit_set(deger,11-i); //Değer ataması 11. bitten 0. bite doğru yapılır. Çünkü ADC ilk önce en yüksek değerlikli biti(MSB) gönderir.
}
else if (input(dout)==0) { //Dout 0 ise "deger" değişkeninin ilgili biti "0" yapılır.
bit_clear(deger,11-i);
}
delay_us(sure); //Clk sinyali belirlenen süre kadar "0" durumunda tutulur.
}//For bitişi
return (deger);
}//Fonksiyon bitişi.
//****************************************
//*********************************************
void menu_1() { //Menünün 1. kısmını oluşturan fonksiyon. Single/Diff seçim ekranı.
//glcd_init(ON);
glcd_rect(1,1,127,63,NO,ON); //Çerçeve
glcd_text57(2,2,baslik,1,ON); //Başlık(MCP3204 Harici ADC)
glcd_text57(2,10,mod,1,ON); //Mod
glcd_rect(1,17+8*cursor,50,25+8*cursor,YES,ON); //Menüde seçim yapmamızı sağlayan dikdörtgen(imleç).
//cursor değişkeni 1 bitlik değişkendir yalnızca 0 ve 1 değerini alabilir.
//cursor'un aldığı değere göre dikdörtgen ilgili yere çizilir ve dikdörtgenin içi boyanır.
//Dikdörtgenin içi boyandığı için, dikdörtgenin içindeki yazının rengi "OFF(0)" yapılmalıdır.
glcd_text57(2,18,single,1,cursor); //cursor=0 iken imleç "single" yazısının üzerinde durur. Bu yüzden "single" yazısının rengi cursor=0 iken "off", cursor=1 iken "on" olmalıdır.
glcd_text57(2,26,diff,1,!cursor); //cursor=1 iken imleç "different" yazısının üzerine durur. "different" yazısının rengi cursor=1 iken "off", cursor=0 iken "on" olmalıdır.
glcd_text57(2,50,uyari,1,ON); //Restart=3xSec yazısı
}
void menu_2() { //Menünün 2. kısmını oluşturan fonksiyon. Kanal seçim ekranı.
switch (cursor_2) { //cursor_2 imlecin(içi dolu dikdörtgen) yerini belirler.
case 0:
k[0]=0; //k[0]=menünün dinamik kısmının(kanalların yazdığı kısım) 1. satırının rengini ayarlayan değişken.
k[1]=1; //k[1]=menünün dinamik kısmının 2. satırının rengini ayarlayan değişken.
k[2]=1; //k[2]=menünün dinamik kısmının 3. satırının rengini ayarlayan değişken.
k[3]=1; //k[3]=menünün dinamik kısmının 4. satırının rengini ayarlayan değişken.
data0=0; //imleç 1. satırdayken 1. satırın renk ayarı "0" diğer satırların renk ayarları "1" yapılır.
data1=0; //1. satır seçildiğinde data0 ve data1 "0" değerini alır.
break;
case 1:
k[1]=0;
k[0]=1;
k[2]=1;
k[3]=1;
data0=1;
data1=0;
break;
case 2:
k[2]=0;
k[1]=1;
k[0]=1;
k[3]=1;
data0=0;
data1=1;
break;
case 3:
k[3]=0;
k[0]=1;
k[2]=1;
k[1]=1;
data0=1;
data1=1;
break;
}
if (cursor==0) { //Single mod.
glcd_rect(1,1,127,63,NO,ON);
glcd_text57(2,2,baslik,1,ON);
glcd_text57(2,10,kanal,1,ON);
glcd_rect(1,17+cursor_2*8,50,25+cursor_2*8,YES,ON); //cursor_2'nin değerine göre imlecin yeri belirleniyor.
glcd_text57(2,18,ch0,1,k[0]);
glcd_text57(2,26,ch1,1,k[1]);
glcd_text57(2,34,ch2,1,k[2]);
glcd_text57(2,42,ch3,1,k[3]);
glcd_text57(2,50,uyari,1,ON);
sd=1;
} // if(cursor==0)
//********************************************
else { //Different(fark modu) okuma
glcd_rect(1,1,127,63,NO,ON);
glcd_text57(2,2,baslik,1,ON);
glcd_text57(2,10,kanal,1,ON);
glcd_rect(1,17+cursor_2*8,50,25+cursor_2*8,YES,ON); //cursor_2'nin değerine göre imlecin yeri belirleniyor.
glcd_text57(2,18,ch0_1,1,k[0]);
glcd_text57(2,26,ch1_0,1,k[1]);
glcd_text57(2,34,ch2_3,1,k[2]);
glcd_text57(2,42,ch3_2,1,k[3]);
glcd_text57(2,50,uyari,1,ON);
sd=0;

}//else
}
//*****************************************************************************
//*****************************************************************************
void grafik() {
j++;
glcd_line(j,63-(volt_int[0]/103),j+1,63-(volt_int[0]/103),ON); //Grafik çizilirken dijital sinyal analog sinyale çeviriliyor gibi düşünülebilir.
glcd_line(j+1,63-(volt_int[0]/103),j+1,63-(volt_int[1]/103),ON); //"Zero Order Hold" denen dijital-analog çevirme yöntemiyle grafik, yazının bittiği yerde başlayarak çizilir.(x=0-128 arası, y=25-63 arası)
if (j==128) { //lcd'ye çizilecek grafiğin x değeri j ye bağlı artar, y ise genliktir ve adc'den okunan değere göre artar.

for (i=0;i<=128;i++) { //Grafiğin çizilidği alan temizlenir.
 for (j=24;j<=64;j++) {
 glcd_pixel(i,j,OFF); //Grafik alanı siliniyor.
 }
}
j=0;
}
}
void main()
{
setup_timer_1(T1_DISABLED); // T1 zamanlayıcısı devre dışı
setup_timer_2(T2_DISABLED,0,1); // T2 zamanlayıcısı devre dışı
setup_adc_ports(NO_ANALOGS); // ANALOG giriş yok
setup_adc(ADC_OFF); // ADC birimi devre dışı
setup_psp(PSP_DISABLED);
setup_CCP1(CCP_OFF); // CCP2 birimi devre dışı
setup_CCP2(CCP_OFF); // CCP2 birimi devre dışı
glcd_init(ON); // Grafik LCD hazırlanıyor ve ekran siliniyor
while(TRUE)
{
basla:
//******************************************
do {
if (select==0) { //select:seçim yapılıp yapılmadığını saklayan değişken.
j=0; //bir kanalın bilgisi izlendikten sonra başka bir kanala geçiş yapılırsa grafiğin x=0 noktasından başlaması için j=0 yapılır.
menu_1();
if (input(asagi)) { //aşağı tuşuna basıldığında,
while(input(asagi)); //elimizi butondan çekene kadar beklenir.
glcd_init(ON);
cursor++; //imleç aşağı alınır.
//Cursor=0 iken imleç yukarıda(Single seçili), =1 iken imleç aşağıdadır(Diff seçili).
//Bu durumda yukarı butonuna ihtiyaç yoktur.
//Fakat kanal seçerken 4 satır olacak yukarı butonu işleri kolaylaştırabilir.
}
if (input(yukari)) {
while(input(yukari));
glcd_init(ON);
cursor--;
}
if (input(sec)) {
while(input(sec));
glcd_init(ON);
select=1; //birinci menüde seçim yapıldığını ifade eder, 2. menüye geçilir.
}
} //if(select==0)
//*******************************
if (select==1) {
menu_2();
if (input(asagi)) {
while(input(asagi));
glcd_init(ON);
cursor_2++;
if (cursor_2==4) cursor_2=0; //2. menü 4 seçimden oluşyor bu yüzden cursor_2 4 değerini alırsa değeri 0'a eşitleniyor.
}
if (input(yukari)) {
while(input(yukari));
glcd_init(ON);
cursor_2--;
if (cursor_2==255) cursor_2=3;
}
if (input(sec)) {
while(input(sec));
//Cursor_2 veya k değişkenlerine göre çeşitli değişkenler farklı değerler alır.
//Şimdilik sadece ekranı temizleyelim.
glcd_init(ON);
select=2;//ikinci menüde de seçim yapıldığını gösterir.
}
}//if(select==1)
} while(select!=2);
//*****************************************************
if (input(sec)&&select==2) {
while(input(sec));
sayac++;
}
if (sayac==3) {
select=0;
sayac=0;
glcd_init(ON);
goto basla;
}
MCP3204_init();
volt_int[0]=volt_int[1];
volt_int[1]=MCP3204(sd,data2,data1,data0); //Default: Single mod, CH0.
for (i=0;i<=11;i++) {
if (bit_test(volt_int[1],i)==1) string[11-i]="1"; //12-Bit şeklinde görüntülenmek üzere char dizisine değerler atanıyor.
else string[11-i]="0";
}//for(i=0;i<=11;i++)
//String halini yazdırabilmek için LSB sıfırıncı elemana değil 11. elemana atılmalıdır.
//Çünkü GLCD'de 0. bitten 11. bite doğru yazdırılır. Böyle yapılsaydı LSB en solda olacaktı.
//Kullanıcıya doğru bilgi aktarımı için dizinin 0. elemanına LSB yerine MSB yazılmıştır.
//***************************************************************************************
//***************************************************************************************
//GLCD:
//Gerilim büyüklüğünü görüntüleyebilmemiz için float cinsinden bir değişkene ihtiyacımız var.
//Gerilim: Volt=x*5/4095 ifadesiyle bulunur.
//Gerilim kesirli sayı olduğundan float tipindedir.
//Float tipini stringe çevirmeliyiz.
//İlk önce sayının tam kısmı elde edilip, char dizisine atanır.
//Daha sonra sayının noktadan sonraki kesirli kısmı elde edilir.
//Char dizisinin ilk elemanı sayının tam kısmı, ikinci elemanı nokta, üçüncü ve dördüncü elemanları kesirli kısımdır.
//Bu örnekte simülasyonda potansiyometre aracılığıyla gerilim ölçüldüğünden tam kısım tek haneli bir sayı, kesirli kısım ise iki haneli bir sayı olmaktadır.
//Bu yüzden bu şekle göre stringe çevrilme işlemi yapılır.
//Eğer sayı virgülden önce 3 elemanlı, virgülden sonra 5 elemanlı olacak olsaydı ufak değişiklikler gerekecekti.
//***************************************************************************************
//Float to Str - 1:
volt_int[2]=volt_int[1]*5/4095; //Kesirli sayının tam kısmı elde edildi.
itoa(volt_int[2],10,str_float); //str_float değişkenine yazıldı.
volt_int[2]=(volt_int[1]*5.000/4095.000-volt_int[2])*100.000; //Virgülden sonrası yazıldı.
itoa(volt_int[2],10,str_float+2);
str_float[1]='.';
str_float[4]=0; //GLCD saçmalamasın diye belirtilmiştir.
//****************************************************************************************
//*****************************************************************************************
grafik(); //grafik çizdiriliyor. itoa'dan sonra yazılınca volt_int[1] değeri değişiyor(?)
itoa(volt_int[1],10,y); //String haline çevrildi, yazılmaya hazır.
if (volt_int[1]!=volt_int[0]) { //Okunan değer değiştiğinde yazı alanı temizlenir, tekrar yazılır.
for (i=0;i<=72;i++) {
for (z=0;z<=24;z++) {
glcd_pixel(i,z,OFF); //Yazı alanı siliniyor.
}
}
}
glcd_text57(1,1,string,1,ON); //İkilik tabanda yazdırılıyor.
glcd_text57(1,9,y,1,ON); //Onluk tabanda yazdırılıyor.
glcd_text57(1,17,str_float,1,ON); //Gerilim değeri yazdırılıyor.

} //while(1)
} //void main


Bir çalışmanın daha sonuna geldik. Kodlar biraz uzun ve karmaşık gözükebilir. Fakat yeterli incelemeden sonra kavrayacağınızı düşünüyoruz. Zaman ayırıp okuduğunuz için teşekkürler. Takipte kalın!


-Roboturka Ailesi

Buna Benzer Yazılar Göster !
Daha Fazlasını Yükle - Konuk Yazar
Daha Fazla Göster -  PIC Assembly - PIC C

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bak Bakalım ?

Esnek Algılayıcı Kontrollü Robotik El

Merhaba arkadaşlar… Ben İbrahim GÖKBAYRAK. Mekatronik mühendisiyim. Bu çalışmada sizlere e…