Elektronik / Elektronik Kaynakları/

C ile PIC Programlama ve PICC Lite Derleyicisi

C programlama Dili : Günümüzde en yaygın olarak kullanılan programlama dillerinden biridir. Bir PC ve bir mikrokontrolör için yazılmış olan C derleyicileri her ne kadar birbirlerine benzeseler de aralarında bazı önemli farklar vardır. PC için yazılmış olan bir C derleyicisi genellikle daha büyük olup programcıya çok çeşitli fonksiyonlar sunmaktadır (örneğin dosya açıp kapama, dosya okuma vs). Bunun yanında, mikrokontrolör için yazılmış olan bir C derleyicisi daha küçük olup programcıya sunulan fonksiyon sayısı da oldukça sınırlıdır. Bununla birlikte, standart C dilini öğrenmiş olan bir programcı, kullanmış olduğu mikrokontrolörün mimarisini de bildiği takdirde çok kolaylıkla C dilinde program geliştirebilir.

PIC mikrokontrolörler için yazılmış olan çok sayıda C derleyicileri bulunmaktadır. Örneğin, Forest Electronics firmasının sunduğu FED C, Hi-Tech firmasının ürünü olan PICC ve yine ayni firmanın ürünü olan ve ücretsiz olarak verilen PICC Lite, CCS firmasının PCM ve PCW derleyicileri ve bunun gibi daha birçokları.

Bu projede Hi-Tech firmasının ürünü olan ve oldukça popüler olan PICC Lite C derleyicisi kullanılmıştır.

PICC Lite Derleyici : Hi-Tech firması tarafından geliştirilmiş olan ve ANSI C standardını izleyen bu C derleyicisi pek çok özelliklere sahip olup birçok endüstriyel uygulamalarda, öğretim ve öğrenim amaçlı, ve ayni zamanda elektronik hobi olarak kullanılmaktadır.

PICC Lite derleyicisi, yine ayni firmanın ürettiği ve pazarladığı PICC derleyicisine çok benzemekte olup, ücretsiz olduğu için bazı kısıtlamaları bulunur. Örneğin, PICC Lite sadece 16C84, 16F84, 16F84A, 16F627, 12F629, 16F877 ve 16F877A PIC mikrokontrolörleri için kullanılabilir. Bunun yanında, sadece 2 tane RAM bankı desteklemektedir (2 bank PIC16F84 için yeterli olduğu halde, PIC16F877 için yeterli olmayabilir) ve 16F877 ve 16F877A mikrokontrolörleri kullanıldığında ROM kapasitesi 2K olarak sınırlandırılmıştır. Ayrıca, PICC Lite derleyicisinde printf fonksiyonu long ve float veri çeşitleri için kullanılamaz. Bu kısıtlamalar dışında PICC Lite ve PICC derleyiciler ayni olup her iki derleyiciyi de kullanarak çok karmaşık PIC uygulamaları geliştirmek mümkündür.

Bu bölümde, PICC Lite derleyicisinin özelliklerini ve bu derleyici ile C programı geliştirmeyi inceleyeceğiz.

PICC Lite Veri Çeşitleri : PICC Lite C derleyicisi aşağıda belirtilen veri çeşitlerini desteklemektedir. Burada küçük harf kullanıldığına dikkat edilmelidir. .

bit
unsigned char
signed char
unsigned int
signed int
long
unsigned long
float
double

Şimdi bu veri çeşitlerini örneklerle daha yakından inceleyelim.

Bit : Bu veri çeşidinde sayılar Boolean (0 veya 1) olabilir. Örneğin, aşağıdaki tanımda değişken flag sadece 0 veya 1 değerlerini alabilir.

bit flag;

unsigned char : Bu veri çeşidi ile 8 bitlik sayılar tanımlanır ve bu sayılar 0 ve 255 arasında değer alabilirler. Örneğin, aşağıdaki veri tanımında değişken q, 0 ve 255 arasında herhangi bir değer alabilir ve burada q 180 olarak değerlendirilmiştir. Aynı zamanda, değişken a karakter R ye eşitlenmiştir. unsigned char tanımı ile hem 8 bitlik bir integer ve hem de bir karakter tanımlanabilir:

unsigned char q,a;
q = 180;
a=’R’;

Burada dikkat edileceği gibi, C dilinde her satır noktalı-virgül (“;”) işareti ile bitmektedir. Satır sonuna bu işaret konulmadığı takdirde derleyici hata verecektir.

signed char : İşaret içeren bu veri tanımı, -128 ve +127 arasındaki sayıları tanımlamak için kullanılır. Aşağıdaki örnekte değişken p’ye¬50 değeri ve değişken z’ye 28 değeri verilmiştir:

signed char p,z;
p = -50;
z = 28;

unsigned int : Bu tanım ile 16 bit olan ve 0 ile 65535 arasında değişen sayılar tanımlanabilir. Aşağıdaki örnekte, değişken q’ya 915 ve değişken x’e 3000 değerleri verilmiştir:

unsigned int q;
q = 915;
x = 3000;

signed int : İşaret içeren ve 16 bitlik sayılar için kullanılan bu tanımda, sayının -32768 ve +32767 arasında olması gerekir. Aşağıdaki örnekte değişken t’ye -500 değeri verilmiştir:

signed int t;
t = -500;

long : 32 bit ve işaret içeren sayılar için kullanılan bu tanımda sayının -2147483648 ve +2147483647 arasında olması gerekir. Örneğin, aşağıdaki tanımda değişken m long olarak tanımlanmış ve değeri 200000 yapılmıştır:

long m;
m = 200000;

unsigned long : 32 bit işaretsiz sayılar için kullanılan bu tanımda sayıların 0 ve 4294967295 arasında olması gerekir. Aşağıdaki örnekte değişken k unsigned long olarak tanımlanmış ve değeri 2000000 yapılmıştır:

unsigned long k;
k =2000000;

float : Bu tanım 24 veya 32 bitlik kayan nokta değişkenler için kullanılır. . Kayan nokta değişkenler matematik işlemlerinde çok önem taşımaktadırlar. Aşağıdaki örnekte değişken temp’e 1.23 değeri verilmiştir:

float temp;
temp = 1.23;

double : Bu tanımda sayılar 24 veya 32 bit olabilmektedir. Aşağıdaki örnekte değişken sum 12.45 değerini almaktadır:

double sum;
sum = 12.45;

Değişkenlere Tanım Esnasında Değer Vermek : C programlama dilinde değişkenlere tanım esnasında değer vermek mümkündür. Örneğin, aşağıda değişken temp’e tanım esnasında 10 değeri ve değişken x’e ise karakter ‘A’ değeri verilmiştir:

unsigned int temp = 10;
unsigned char x = ‘A’;

Programda Açıklayıcı Yazılar : İki tane öne eğik çizgiden (“//”) sonra yazılanlar derleyici tarafından öneme alınmamakta ve programın çalışmasını kolay anlamak için bu tip açıklayıcı yazılar tavsiye edilmektedir:

i = 0; //i değişkenini sıfır yap
j = j + 2; //j değişkenine 2 ilave et
//şimdi iki sayıyı çarp
// ve neticeyi sakla

Açıklamaları bir diğer şekilde yazma formatı ise, açıklamayı “/*” karakterleri ile başlatmak ve “*/” karakterleri ile bitirmektir. Aşağıdaki örnekte bu açıklama şekli gösterilmiştir:

/* Bu program iki tane sayıyı toplar.
Sayılardan biri x, diğeri ise y dir.
Netice z de saklanir.

*/

z = x + y;

Herhangi bir programda her iki tanım şeklini de kullanmak mümkündür.

Değişkenlerin Bellekte Saklanması : PICC Lite C derleyicisinde değişkenler normal olarak RAM bellekte (genel maksatlı yazmaçlarda) saklanmaktadır. Eğer bir değişkenin değeri sabitse ve program boyunca değişmeyecekse, o değişkeni program belleğinde (EPROM veya Flash) saklamak mümkündür. Bu şekilde, kapasitesi sınırlı olan RAM belleği çok kullanılmamış olur.

Sabit bir değişkeni program belleğinde saklamak için önüne const komutu ilave edilmeli ve değişkenin değeri tanım esnasında belirtilmelidir. Aşağıdaki örnekte temp1 değişkeni RAM belleğinde saklanır, temp2 değişkeni ise 12 değerini alır ve program belleğinde bir sabit olarak saklanır. Burada temp değişkeninin değeri program boyunca sabit olup program içerisinde değiştirilemez. temp 1 değişkeni ise istenildiği gibi ve istenilen an değiştirilebilir:

int temp1 ;
const int temp = 12;

Diziler (arrays) : benzeri bir takım değişkenleri bir grup altında toplamak için kullanılırlar. Örneğin,

int sonuc[6];

Komutu Şekil 1.1 de gösterildiği gibi 6 tane tam sayı tanımlar ve bu tam sayıların ilki sonuc[0], ikincisi sonuc[1], ve sonuncusu ise sonuc[5] olmaktadır.

Şekil 1.1- 6 elemanlı bir dizi

Örneğin, sonuc[3] = 18 komutu sonuc dizisinin 4üncü elemanını 18 sayısına eşitler. Aynı şekilde, sonuc[2] = sonuc[1] komutu sonuc dizisinin 2inci elemanını 3üncü elemanına eşitler.

Bir dizinin elemanları RAM bellekte veya program belleğinde saklanabilirler. Eğer elemanların değerleri sabitse ve program boyunca değişmeyecekse, const komutu kullanarak bu elemanlar program bellekte saklanabilirler. Bu şekilde, kapasitesi kısıtlı olan RAM bellek de kullanılmamış olur. Aşağıdaki örnekte 5 elemanlı temp dizisinin elemanları program bellekte saklanırlar. Bu dizi bellekte 10 bayt tutar (her integer 2 bayt yer tutar):

const int temp[ ] = {1, 5, 9, 12, 45};

Aşağıdaki örnekte ise temp dizisi RAM bellekte 10 bayt tutar:

int temp[ ] = {1, 5, 9, 12, 45};

C programlama dilinde string değişkenleri ASCII 0 ile sonlandırılan ve bir takım karakterler ihtiva eden dizilerdir. Bu durumda,

char name[ ] = “Suzan”;

Komutunda derleyici otomatik olarak name stringi için sonuncu karakteri ASCII 0 olan 6 karakter ayırır. Bu örnekte dizi RAM bellekte saklanmıştır. Aynı dizinin başına const komutu koyarak diziyi program bellekte saklayabiliriz.

Diziler birden çok boyutlu olabilirler. Aşağıdaki örnekte ve Şekil 1.2 de 2 boyutlu bir dizi tanımlanmıştır:

int temp[3][5];

Şekil 1.2 iki boyutlu bir dizi

Burada temp, 3 sırası ve 5 sütunu olan bir dizi olarak düşünülebilir. Dizinin ilk elemanı temp[0][0], ikinci elemanı temp[0][1], üçüncü elemanı temp[0][2] vs dir.

Örneğin, temp[0][1] = 10 komutu dizinin ikinci elemanını 10 sayısına eşitler.

Dizi elemanlarını tanım esnasında belirtmek mümkündür. Aşağıdaki örnekte test dizisi RAM bellekte saklanmış ve elemanları test[0]=2, test[1]=5, ve test[2]=8 olarak belirlenmiştir:

int temp[3] = {2,5,8};

Daha önce bahsedildiği gibi, const komutunu kullanarak dizi elemanlarını program bellekte sabit olarak saklayabiliriz.

Program değişkenleri : bir karakter veya alt çizgi (“_”) ile başlamalı ve bunu takiben istenilen miktarda karakter veya 0¬-9 arasında sayı kullanılmalıdır. Aşağıdakiler geçerli olan bazı program değişken isimleridir:

size
toplam_miktar
max5
_ortalama
j
ge2ci23ci
a_b_c_d

Static değişkenler : Genel olarak bir fonksiyonda bulunan ve fonksiyonu her kullanışta değerleri değişmeyen değişkenlerdir. Bu değişkenleri tanımlarken isimleri başına static yazılır. Örneğin, bir fonksiyona girişte, fonksiyonda daha önce kullanılan bir değişkenin değeri belirsizdir. Fakat değişkeni static yapmakla değerini muhafaza etmiş oluruz.

Volatile değişkenler : Bir değişkenin her kullanıldığında eski değerini muhafaza edemeyeceği durumlarda kullanılır. Bütün giriş-çıkış portları ve kesme rutinlerinin değiştirdiği değişkenler volatile yapılmalıdır.

Persistent Değişkenler : Genel olarak PIC mikrokontrolör reset yapıldığında programda kullanılan bütün değişkenler ilk olarak sıfır değerini alırlar. Yalnız bazı durumlarda, birtakım değişkenlerin reset esnasında değerlerini kaybetmelerini istemeyebiliriz. Herhangi bir değişkenin ismi önüne persistent kelimesini yazmakla o değişkenin reset esnasında sıfırlanmasını istemediğimizi belirtiriz.

Mutlak Adres Değişkenleri : Bir değişkenin ismi sonuna “@” karakteri konarak o değişkene bir mutlak adres değeri verilebilir. Örneğin,

unsigned char Portbit @ 0x06;

Yukarıdaki satırda belleğin 6 ncı adresinde Portbit diye bir değişken tanımlanmıştır. Burada derleyici Portbit değişkeni için bir yer ayırmaz, fakat sadece Portbit ismini mutlak adres 6 ya eşitler. Bu tanımın assembler eşiti şudur:

Portbit EQU 06h

Bit veri çeşidi ve mutlak adres birleştirilip istenilen bir adresteki herhangi bir bit okunup değiştirilebilir. Örneğin, STATUS yazmacı bellekte adres 3 tedir. Bu yazmacın 3 üncü bitini istiyorsak, STATUS yazmacını adres 3 de tanımlayıp 3×8 + 3 = 27 nci biti şu şekilde tanımlayabiliriz:

static unsigned char STATUS @ 0x03;
static bit PD @ (unsigned)&STATUS*8+3;

Burada PD değişkeni bellekteki 27 nci biti (STATUS yazmacının 3 üncü biti) tanımlamıştır.

Operatörler : Herhangi bir programlama dilinde operatörler son derece önem taşımaktadırlar. Bütün aritmetik ve lojik işlemler bu operatörler sayesinde yapılmaktadır. PICC Lite derleyicisi aşağıdaki operatörleri desteklemektedir:

() [] parentez
! lojik NOT
~ bit tersi
+ – * / aritmetik operatör
% modulus
++ artır
eksilt
& adresi
<< >> kayma (shift) operatörleri
>= büyüktür veya eşittir operatörü
> büyüktür operatörü
<= küçüktür veya eşittir operatörü
< küçüktür operatörü
sizeof bir değişkenin kaç bayt olduğu
= = lojik eşittir operatörü
!= lojik eşit değildir operatörü
|| lojik OR
&& lojik AND
+= -= /= eşitlik operatörleri
|= ^= %= eşitlik operatörleri
&= <<= >>= eşitlik operatörleri

Program Akış Kontrolü : Program akışını değiştiren komutlar assembler dili de olmak üzere her programlama dilinde son derece önemlidirler. Bu komutlar sayesinde döngü yapabiliriz veya bir değişkenin değerine bağlı olarak değişik işlemler yapabiliriz. PICC Lite aşağıdaki program akış kontrol komutlarını destekler:

if-else
for
while
do
goto
break
switch – case

Şimdi bu komutların kullanımlarını daha yakından inceleyelim.

if – else : Koşula bağlı olarak program akışını değiştiren bu komut genel olarak şu şekillerde kullanılabilir:

if(koşul)komut;

veya,

if(koşul)
{
komut;
komut;
……….
……….
komut;

}

veya,

if(koşul)
{
komut;
komut;
……….
}
else
{
komut;
komut;
……….
}

sadece bir komut içeren durumlarda şu şekilde de kullanılabilir:

if(koşul)
komut;
else
komut;

Burada, komutlar sonunda noktalı-virgül işaretlerine dikkat ediniz.

Aşağıdaki örnekte, p değişkeni 0 ise b değişkeni 1 olarak artırılır, aksi halde b değişkenine 2 ilave edilir:

if(p = = 0)
b=b+1;
else
b=b+2;

Yukarıdaki örnekte eşittir operatörü olan “= =” karakterlerinin kullanıldığına dikkat ediniz.

for : For komutu program içerisinde döngü yapmak için kullanılır. Döngü bir veya birtakım komutu birden fazla tekrarlamak maksadıyla kullanılır. Bu komut şu şekillerde olabilir:

for(başla; koşul; artış)komut;

veya,

for(başla; koşul; artış)
{
komut;
komut;
……….
}

burada, başla döngü değişkeninin ilk değerini, artış ise son değerini belirtmektedirler.

Aşağıdaki örnekte döngü değişkeni i, 1 den 10 a kadar gitmekte ve sayac değişkeni 10 defa artırılmaktadır.

for(i = 1 ; k = 10; i + + )sayac+ +;

for komutunu kullanarak iç içe döngü yapmak mümkündür. Aşağıdaki örnekte iç döngü 5 defa ve dış döngü ise 10 defa tekrarlanmaktadırlar:

for(i=0; i<10; i+ +) { for(j=0; j<5; j+ +) { komut; ......... } }

while : Döngü yapmak için kullanılan bir başka komut da while komutu olup bu komutun genel kullanım şekli şu şekildedir:

while(koşul)komut;

veya,

while(koşul)
{
komut;
komut;
………
}

Belirtilen koşul doğru olduğu müddetçe döngü devam etmektedir. Eğer döngü başında seçenek doğru değilse döngü içerisindeki komutlar işlem görmezler. Aşağıdaki örnekte döngü 10 defa tekrarlanmaktadır:

i=0;
while(i < 10) { komut; komut; i++; }

while komutunu kullanırken döngü içerisinde koşulun sağlanmasına dikkat etmemiz gerekir, aksi halde sonsuz bir döngü elde etmiş oluruz.

do : Döngü yapmak için kullanılan bir diğer komut ise do komutudur. Burada seçenek döngünün sonunda kontrol edilir ve bundan dolayı koşul doğru olmasa bile döngü en az¬ bir defa çalışmış olur. Bu komutun genel kullanımı şu şekildedir:

do
{
komut;
komut;
……..
}while(koşul);

Aşağıdaki örnekte döngü değişkeni j, 0 dan 5 e kadar gitmekte ve döngü 5 defa tekrarlanmaktadır:

j = 0;
do
{
komut;
komut;
j++;
}while < 5);

while komutunu kullanırken döngü içerisinde koşulun sağlanmasına dikkat etmemiz gerekir, aksi halde sonsuz bir döngü elde etmiş oluruz. Ayni zamanda, koşul sağlansa bile döngü en az bir defa yapılmaktadır.

break : break komutu, bir döngü içerisinde ve döngü bitmeden, döngü dışına çıkmak için kullanılmaktadır. Aşağıdaki örnekte j değişkeni 10 olunca döngü durur ve döngü sonrasındaki komutlar işlem görürler. Bu komut bir sonra göreceğimiz switch-case komutunda çok kullanılmaktadır:

while(i < 100) { komut; komut; if(j = = 10)break; }

switch – case :Bu komut, çoklu if-else komutu gibi görev yapmaktadır. Bir değişken alınır ve bu değişkenin değerine bağlı olarak çeşitli komutlar işlem görürler.

Aşağıdaki örnekte, sec değişkeninde bulunan ve ‘A’ ve ‘F’ arasında olan 1-digit bir hexadecimal sayının decimal sayıya dönüştürülmesi gösterilmiştir. Dönüştürülen sayı hex gibi bir değişkende saklanmıştır:

Switch(sec)
{
Case’A’: hex = 65;
break;
Case’B’: hex = 66;
break;
Case’C’: hex = 67;
break;
Case’D’: hex = 68;
break;
Case’E’: hex = 69;
break;
Case’F’: hex = 70;
break;
default: hex = 0;
break;
}

Burada, sec değişkeninin değeri ‘A’ ise hex değişkeni 65 olur, ‘B’’ ise hex değişkeni 66 olur, ‘C’ ise hex değişkeni 67 olur v.s. Eğer sec değişkeni ‘A’ ve ‘F’ arasında değilse default komutu çalıştırılır ve bu örnekte hex değişkeni 0 a eşitlenir. switch-case komutunda break komutunun çok sık olarak kullanıldığına dikkat ediniz (eğer break kullanılmazsa program bir sonraki koşula devam etmektedir).

Kullanıcı Fonksiyonları :Fonksiyonlar genel olarak bir program içerisinde kullanılan ve ana programdan bağımsız programdırlar. Her fonksiyonun bir ismi olup istenilirse bir fonksiyon ana programa bilgi aktarabilir. Başında void komutu ile başlayan fonksiyonlar ana programa bilgi aktaramazlar. Örneğin, aşağıdaki fonksiyonun ismi ledon olup bu fonksiyon ana programa bilgi aktarmaz.

void ledon()
{
led = 1;
}

Aşağıdaki ledon fonksiyonu ise ana programa integer bir bilgi aktarır:

int ledon()
{
komut;
komut;
return(değişken);
}

Fonksiyonlar ana programdan bilgi alıp bu bilgiyi işler ve tekrar ana programa bilgi aktarabilirler. Aşağıdaki örnekte kare fonksiyonu ana programdan bir integer değer alır (parameter) ve bunun karesini alıp ana programa aktarır:

int kare(int y)
{
int w;
w = y*y;
return (w) ;
}

Bu fonksiyon ana program tarafından şu şekilde kullanılabilir:

s = kare(p);

Kare fonksiyonu ana programdan p değişkeninin değerini alır ve bu sayının karesini alıp geri ana programa aktarır. Fonksiyon başındaki int tanımı fonksiyonun ana programa integer (tam sayı) aktaracağını gösterir. Bu durumda, ana programdaki s değişkeni p nin karesine eşitlenmiş olur.

Burada önemli olan bir nokta, fonksiyonda kullanılan w ve y değişkenleri sadece fonksiyona ait olup ana programda olan bir w veya y değişkeni ile hiçbir ilgileri yoktur. Ayni zamanda, ana programda kullanılan bir değişken ile fonksiyonda kullanılan ve aynı ismi taşıyan herhangi bir değişken arasında bir bağıntı yoktur.

Örnek 3.2
Tabanı ve yüksekliği bilinen bir üçgenin alanını hesaplayan bir fonksiyon yazınız ve bulduğunuz alanı ana programa aktarınız.

Çözüm 3.2
Tabanı ve yüksekliği bilinen bir üçgenin alanı, olarak bulunabilir. Bu durumda, istenilen fonksiyon aşağıda verilmiştir. Değişkenlerin herhangi bir sayı olabilecekleri göz önünde bulundurularak float veri çeşidi kullanılmıştır:

float alan(float taban, float yukseklık)
{
float i;
i = (taban * yukseklik)/2;
return(i) ;
}

Tabanın 23.2 ve yüksekliğin ise 3.4 olduğunu kabul edersek bu fonksiyon ana program tarafından şu şekilde çağrılabilir:

hesap = alan(23.2, 3.4);

Burada, alan fonksiyon tarafından hesaplanır ve hesap diye adlandırılan bir değişkende saklanır. hesap değişkeni, ana programda float olarak tanımlanmalıdır.

Ön-işlemci Direktifleri : PICC Lite derleyici, diğer standart C derleyicilerde bulunan çeşitli ön-işlemci direktiflerini destekler. Yaygın olarak kullanılan ön-işlemci direktifleri aşağıda açıklanmıştır.

#define : Bu direktif program başında kullanılır ve bir makro gibi çalışıp semboller yerine tanımlanan eşitlerini koyar.

Örneğin;
#define size 10
#define max 100
#define min 0

program içerisinde bu semboller kullanıldığı zaman yerlerine otomatik olarak değerleri konur:

a = 1; // a değişkenini 1 yap
a = a + size; // a değişkeni 11 değerini alır

define direktifi çok kompleks de olabilmektedir. Aşağıdaki makro tanımında 2*(a+b) işlemi mult(a,b) olarak tanımlanmıştır:

#define mult(a,b) 2*(a + b)

Şimdi bu makronun bir program içerisinde kullanımına bakalım.

a = 2; // a değişkenini 2 yap
b = 5; // b değişkenini 5 yap
c = mult(a,b); // c değişkeni 2*(2+5)=14 olur

Örnek 3.3
Bir integer 2 bayt’tan meydana gelmektedir. Böyle bir integer’in üst ve alt byte’larını almak için “define” komutunu kullanarak makro yazınız.

Çözüm 3.3
Üst baytı almak için sayıyı 8 defa sağa kaydırabiliriz. Makro adına ustbayt dersek,

#define usfbayt(x) (unsigned char)(x>>8)

olur. Alt baytı bulmak için ise, sayıyı, 0xFF (desimal 255) ile mask yapabiliriz. Makro adına altbayt dersek,

#define altbayt(x) (unsigned char)(x & 0xFF)

olur.

Örnek 3.4
Bir değişkenin herhangi bir bitini 1 veya 0 yapmak için “define” direktifini kullanarak bir makro yazınız.

Çözüm 3.4
Herhangi bir biti 1 yapmak için kullanacağımız makroya bit_set dersek, şu şekilde yazabiliriz:

#define bit_set(var, bitno) ((var) -= (1<< (bitno)))

Herhangi bir biti 0 yapmak için, kullanacağımız makroya bit_reset dersek, şu şekilde yazabiliriz:

#define bit_reset(var, bitno) ((yar) &= ~(1<< (bitno)))

Örneğin, x değişkeninin bit 3 ünü 1 yapmak için şu komutu kullanabiliriz:

bit_set(x,3) ;

Aynı şekilde, p değişkeninin 6 cı bitini 0 yapmak için şu komutu kullanabiliriz:

bit_reset(p,6);

#asm ve #endasm : Bu direktifler sayesinde bir assembler programı veya bir veya birkaç assembler komutları C programımıza ilave edilebilir:

……….
……….

a=2;
#asm
movlw 10h
#endasm

………….
………….

Yukarıdaki programda görüleceği gibi assembler komutları #asm ve #endasm direktifleri arasına yerleştirilmelidir.

#include : Bu direktifi kullanarak başka bir text dosyasını programımız içerisine alabiliriz. Örneğin, “myproject.h” dosyası programımıza şu şekilde ilave edilebilir:

#include “myproject.h

veya,

#include

PIC yazılımı geliştirirken dosyası programımıza ilave edilmelidir. Bu dosya içerik olarak PIC mikrokontrolöre ait çeşitli değişkenleri tanımlamaktadır.

Programda Değişik Sayı Tabanı Kullanımı : PICC Lite derleyicisinin normal sayı tabanı 10 (desimal) olup birçok mikroişlemci ve mikrokontrolör uygulamalarında kullanılan sayı tabanının zaman zaman değiştirilmesi gerekmektedir. Örneğin, mikrokontrolör tabanlı kontrol uygulamalarında genellikle 16 tabanı (hexadecimal) veya 8 tabanı (octal) kullanılmaktadır.

Bir sayıyı hexadecimal olarak yazmak için önüne %x (veya %0X), octal olarak yazmak için önüne %o ve ikili tabanda yazmak için ise önüne 0b koymak gerekir. Aşağıda değişik tabanlarda bazı örnekler verilmiştir:

toplam = %0x1f; // toplam = 0001 1111
sum = %o37; // sum = 011 111
a = 0b00001111 // a = 00001111

Yapılar (Structures) : Yapılar, birbirleriyle ilgili olan çeşitli değişkenleri yeni bir değişken altında toplamak için kullanılır. Örneğin, bir şahıs hakkındaki, bir takım bilgiler normal olarak şu şekilde tanımlanabilir:

unsigned char adi[80];
unsigned char soyadi[80];
unsigned int yasi;
unsigned char adresi[80];

Bir yapı (structure) kullanarak yukarıdaki tanımları şu şekilde yazabiliriz:

struct sahsi
{
unsigned char adi[80];
unsigned char soyadi[80];
unsigned int yasi;
urisigned char adresi[80];
}

Bu durumda, sahsi yapısı bir şahıs hakkında olan bütün tanımları bir çatı altında toplamış olur. Bir yapı yukarıdaki gibi tanımlandığı zaman bellekte hiçbir yer tutmaz. Ancak bu yapı bir sonraki örnekte gösterildiği zaman kullanıldığı zaman bellekte yer tutar.

Şimdi, aşağıdaki yeni tanımı yapabiliriz:

struct sahsi benim_bilgiler;

Yukarıdaki tanım ile benim_bilgiler yeni bir değişken olup bu değişkenin çeşidi sahsi’dir ve bu değişken bellekte yer tutar. Şimdi, bu yeni değişkeni kullanarak şu komutu yazabiliriz:

Benim_bilgiler.yasi = 25;

Yapıları kullanarak bir değişkene istenilen sayıda bit ayırabiliriz. Aşağıdaki örnekte x ve y 1 bitlik değişkendirler ve z ise 6 bitlik bir değişkendir. Değişken temp flags çeşidi bir yapıya sahip olup bellekte toplam 1 bayt tutmaktadır:

struct flags
{
unsigned char x:1;
unsigned char y:1;
unsigned char z:6;
}

struct flags temp;

İşaretçiler (Pointers) : C programlama dilinde işaretçi kavramı çok geniş olarak kullanılmaktadır. Genel olarak bir işaretçi bir değişkenin bellekteki adresini gösterir. Örneğin, x bir değişken ise, x’i gösteren bir işaretçi x’in bellekteki adresini tutar. İşaretçiler, değişken ismi önüne “*” karakteri koyarak tanımlanırlar. Değişken çeşidine göre işaretçi çeşidi de değişmektedir. Örneğin, bir karakter işaretçisi bir integer için kullanılamaz. Aşağıdaki örnekte, p bir karakter işaretçisi olarak tanımlanmıştır:

char *p;

Burada p bir karakter işaretçisi olarak tanımlandığı halde şu an herhangi bir yerde kullanılmış değildir. Herhangi bir değişken önüne “&” karakterini koyarak o değişkenin adresini elde edebiliriz. Daha sonra da işaretçi değişkenini kullanabiliriz. Örneğin, işaretçi p’ye, z değişkeninin adresini şu şekilde yükleyebiliriz:

p = &z;

p işaretçisi şimdi z değişkeninin adresini tutmaktadır. “*” operatörünü kullanarak, adresi bilinen bir değişkenin asıl değerini okuyabiliriz. Aşağıdaki örnekte, daha önce tanımlanan z değişkeninin değeri 3 yapılmıştır:

*p = 3;

Herhangi bir değişkenin adresine erişebilme birçok uygulamalarda çok kullanışlı olmaktadır. Bu şekilde daha verimli ve daha kısa programlar geliştirmek, mümkün olabilmektedir.

İşaretçiler dizilerde çok kullanışlı olmaktadırlar. Bir dizinin ismi o dizinin adresini tutmaktadır. Bu durumda, bir işaretçi kullanarak dizi işlemlerini kolaylıkla yapabiliriz. Bir örnek aşağıda verilmiştir:

char buffer[10]; // 10 elemanı olan bir buffer tanımlama
char *p; // p bir karakter işaretçisidir
p = buffer; // p işaretçiye buffer adresi yüklendi
*p = 0; // buffer dizisinin ilk elemanını 0 yap
p++; // p’yi artır (sonraki elemanı adresle)
*p = 1; // buffer’in ikinci elemanını 1 yap

Yukarıda da görüleceği gibi işaretçiler ile çeşitli aritmetik işlemler yapmak ve değişik adreslere gitmek mümkündür.

EEPROM Belleğe Yazıp Okuma : Bazı PIC mikrokontrolörlerde (örneğin PIC16F84) EEPROM bellek bulunmaktadır. Bu belleğe yazıp okumak için PICC Lite derleyicinin EEPROM_WRITE ve EEPROM_READ diye iki tane fonksiyonu bulunmaktadır.

EEPROM_WRITE(adres, veri) fonksiyonu belleğin adresine veriyi yazar. Örneğin, EEPROM_WRITE(5, 12) komutu belleğin 5 inci adresine 12 sayısını yazar.

EEPROM_READ(adres) fonksiyonu belleğin adresinden veri okur. Örneğin, z = EEPROM_READ(14) komutu belleğin 14 üncü adresindeki veriyi okur ve değişken z yi bu veriye eşitler.

Konfigürasyon Bitleri : PIC mikrokontrolörün konfigürasyon bitleri “_CONFIG(x)” komutunu kullanarak istenildiği gibi seçilebilir. Burada x istenilen konfigürasyondur. Aşağıdaki örnekte Bekçi Köpek devreden çıkarılır, XT kristal modu seçilir ve kod koruması yapılmaz:

_CONFIG(WDTDIS & XT & UNPROTECT);

PIC konfigürasyon bitlerini yonganın programlanması esnasında programlayıcı yazılımızla da istediğimiz gibi seçebiliriz.

Yazının Kaynak Dosyası (rft) C ile PIC Programlama ve PICC Lite Derleyicisi

Dosya indirme LINK listesi (TXT formatında) link-3688.zip şifre-pass: 320volt.com
Emeği geçen Kişilere Teşekkürler

Sponsorlu Bağlantılar
  1. aykut doyran 2009/07/08
  2. Serdar 2011/03/05
  3. mustafa 2013/11/16

Yorum

Soru: