Fonksiyonlar, bir programda farklı parametrelerle birden çok kez tekrarlanacak işlemleri yapmak için kullanılan yapılardır. Örneğin 5 adet analog girişi okumak ve ekrana yazdırmak için bir kod yazacağımızı düşünelim. Her analog giriş için, analog giriş seçimi, bekleme, okuma ve ekrana yazdırma işlemi yazmamız gerekir. Bu gibi tekrarlayan işlemlerde fonksiyon içerisinde kodu bir kez yazıp fonksiyonu her çağırdığımızda aynı kod üzerinden farklı 5 adet girişi okumak mümkün kılınır. Bir fonksiyon tek başına bir şey ifade etmez. Fonksiyonların çalışabilmesi için çağrılmaya ihtiyacı vardır.
Örnek bir fonksiyon yapısı şu şekildedir:
1 2 3 4 5 6 7 8 9 10 |
donusTuru fonksiyonum(parametreler){ // Özel fonksiyonumuz /* * Fonksiyon çeğırıldığında * çalışacak kodlar */ } void main(){ // Her programda olması gereken ana fonksiyonumuz fonksiyonum(); // fonksiyonum adlı özel fonksiyonu çağırdık. } |
Yukarıdaki örnek görüldüğü üzere fonksiyonlar “main” fonksiyonu dışında ve main fonksiyonundan önce yazılmalıdır. Main fonksiyonundan sonra tanımlanan fonksiyonlar hata verebilir. Şimdi fonksiyon türlerimizi inceleyelim.
Fonksiyonlar parametre alan ya da almayan, geriye dönüş değeri olan ya da olmayan olarak farklı şekillerde oluşturulabilir.
Şimdi geriye dönüş türüne ve parametrelere göre çeşitli fonksiyon türlerini inceleyelim.
Bu fonksiyonlar tanımlanırken, fonksiyon geriye değer döndürmeyeceği için başına “void” kelimesi eklenir. Ardından fonksiyon adı yazılır ve parantez açıp kapatılır. Fonksiyon parametre almayacağı için parantezler arası boş bırakılır. Ardından küme parantezi ile fonksiyon tanımlama işlemi sona erer. Küme parantezleri içerisine fonksiyon çağırıldığında çalışması istenen kodlar yazılır.
Örnek olarak “fonksiyonum” adında bir fonksiyon tanımlayalım ve bu fonksiyonu her çağırdığımızda “C” portunun “0” nolu pinine bağladığımız ledin 1 saniye aralıklarla yanıp sönmesini sağlayalım;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <16f877a.h> #use delay(crystal=20000000) void fonksiyonum(){ output_high(pin_C0); delay_ms(1000); output_low(pin_C0); delay_ms(1000); } void main(){ while(true){ fonksiyonum(); } } |
Yukarıda görüldüğü üzere main() fonksiyonundan önce fonksiyonum() adında kendi özel fonksiyonumuzu tanımladık. Fonksiyonun küme parantezleri içerisinde, fonsiyonu çağırdığımızda çalışacak kodlarımızı yazdık.
Fonksiyonu tanımlarken başına void kelimesini ekledik. Çünkü fonksiyon çalıştıktan sonra geriye değer döndürmeyecektir. Eğer geriye değer döndüren bir fonksiyon yazacak olsaydık, void kelimesi yerine, geriye dönüş değer türünü (int, char) yazacaktık.
Bir fonksiyon çalıştığında eğer geriye bir değer döndürecek ise, fonksiyonu tanımlarken başına void yerine geriye dönüş değer tipi yazılır.
Örneğin analogRead adında bir fonksiyon yazalım ve fonksiyonu her çağırdığımızda A0 pinindeki analog değeri okuyan fonksiyonumuzu yazalım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <16f877a.h> // denetleyici başlık dosyamız #device ADC=10 // 10 bit ADC kullanılacak #use delay(crystal=20000000) // 20 MHz kristal osilatör kullanılacak float analogRead(){ // analogRead fonksiyonumuz set_adc_channel(0); // A0 ADC kanalını set ediyoruz delay_us(10); // 10 mikrosaniye bekliyoruz return read_adc(); // analog değeri okuyup fonksiyondan geriye döndürüyoruz } void main(){ // main fonksiyonumuz setup_adc(ADC_CLOCK_DIV_32); // ADC frekansı denetleyici frekansımızın 1/32'si olacak setup_adc_ports(ALL_ANALOG); // Tüm analog ririşler kullanılacak float analogDeger; // analogRead() fonksiyonundan dönen değeri tutacağımız değişken while(true){ // Sonsuz döngümüz // analogRead fonksiyonunu çağır ve // gelen değeri analog deger değişkenine ata analogDeger = analogRead(); // eğer dönene değer 255'den büyük ise if(analogDeger > 255){ output_high(pin_C0); // C0 pinini HIGH yap } else{ // değilse (dönen değer 255'den büyük değilse) output_low(pin_C0); // C0 pinini LOW yap } delay_ms(100); // her döngüde 100 milisaniye bekle } } |
Yukarıdaki kodda görüldüğü üzere fonksiyonumuz geriye float türünde değer döndüreceği için analogRead fonksiyonumuzu tanımlarken başına void yerine float türünü ekledik. Ardından fonksiyon içerisinde A0 ADC pinini set ettik ve adc_read() komutu ile A0 pininden okuduğumuz analog değeri “return” komutu ile fonksiyonu çağırdığımız noktaya geri döndürmesini istedik.
return komutu fonksiyondan geriye değer döndürmek için kullanılan komuttur!
main() fonksiyonumuz içerisindeki sonsuz döngümüzde “analogDeger = analogRead()” komutunu kullanarak fonksiyonu çağırdık. Bunun anlamı, analogRead() fonksiyonunu çalıştır ve fonksiyondan return komutu ile dönen değeri analogDeger değişkenine aktar demektir.
Şimdiye kadar fonksiyon tanımlarken parantezler içerisini boş bırakmıştık. Bunun anlamı, fonksiyonun parametre almayacağını belirtmek içindir. Eğer fonksiyonu çağırırken, fonksiyon içerisinde bizim fonksiyona gönderdiğimiz değerlere göre işlem yapmasını istiyorsak fonksiyona partametre olarak değerleri göndermeliyiz. Yani biz fonksiyona “benim gönderdiğim değerlere göre işlem yap” demiş oluyoruz.
Örnek olarak 1 saniye aralıklarla A0, A1, A2, A3 ve A4 analog girişlerini okuyup okunan değerleri LCD ekrana yazdıran projemizi yapalım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#include <16f877a.h> // denetleyici başlık dosyamız #device ADC=10 // 10 bit ADC kullanılacak #use delay(crystal=20000000) // 20 MHz kristal osilatör kullanılacak #define LCD_ENABLE_PIN PIN_D0 // LCD Enable pini D0 pinine bağlı #define LCD_RS_PIN PIN_D1 // LCD RS pini D1 pinine bağlı #define LCD_RW_PIN PIN_D2 // LCD RW pini D2 pinine bağlı #define LCD_DATA4 PIN_D3 // LCD DATA4 pini D3 pinine bağlı #define LCD_DATA5 PIN_D4 // LCD DATA5 pini D4 pinine bağlı #define LCD_DATA6 PIN_D5 // LCD DATA6 pini D5 pinine bağlı #define LCD_DATA7 PIN_D6 // LCD DATA7 pini D6 pinine bağlı #include <LCD.c> // LCD.c kütüphanesini içe aktar float analogRead(int oku){ // analogRead fonksiyonumuz set_adc_channel(oku); // parametre olarak gelen ADC kanalını set ediyoruz delay_us(10); // 10 mikrosaniye bekliyoruz return read_adc(); // analog değeri okuyup fonksiyondan geriye döndürüyoruz } void LCD_Yaz(int analogGirisNo, float ADC_sonuc){ // LCD_yaz fonksiyomuz printf(lcd_putc,"\f"); // Ekranı temizle printf(lcd_putc,"%d NOLU GiRiS:",analogGirisNo ); // Parametre olarak gelen analog giriş numarasını LCD ekrana yaz printf(lcd_putc, "\n%f", ADC_sonuc); // İkinci satıra okunan analog değeri yaz } void main(){ // main fonksiyonumuz setup_adc(ADC_CLOCK_DIV_32); // ADC frekansı denetleyici frekansımızın 1/32'si olacak setup_adc_ports(ALL_ANALOG); // Tüm analog ririşler kullanılacak lcd_init(); // LCD'yi başlat float analogDeger; // analogRead() fonksiyonundan dönen değeri tutacağımız değişken while(true){ // Sonsuz döngümüz for(int i=0; i<5; i++){ // döngü 4 kez devam edecek ve her döngüne i değeri 1 artırılacak analogDeger = analogRead(i); // her döngüde i değerini analogRead fonksiyonuna gönder ve // dönen değeri analogDeger değişkenine aktar LCD_Yaz(i, analogDeger); // LCD'ye hangi analog girişin okunduğunu ve // okunan değerini gönder delay_ms(1000); // her döngüde 100 milisaniye bekle } } } |
Yukarıdaki kodda 2 adet fonksiyon kullandık.
Birinci fonksiyonumuz olan analogRead() fonksiyonumuz, fonksiyona gönderilen parametrelere göre analog giriş değerini okuyup okunan değeri fonksiyonumuzu çağırdığımız noktaya geri döndürecek. Yani analogRead() fonksiyonumuz parametre alan ve geriye değer döndüren fonksiyonumuzdur. Fonkisyonumuzu yazarken parantezler içerisinde belirttiğimiz üzere “int” türünden parametre almaktadır ve fonksiyonun başında belirtttiğimiz üzere geriye “float” türünde değer döndürmektedir.
Bu fonksiyonumuzu çağırırken donenDeger = analogRead(parametre); şeklinde çağırdık.
İkinci fonksiyonumuz ise LCD_Yaz() fonksiyonumuzdur. Bu fonksiyonumuz ise parametre alan ancak geriye değer döndürmeyen “void” fonksiyonumuzdur. LCD_Yaz fonksiyonumuz “int” türünden okunan analog giriş numarasını ve “float” türünden okunan analog girişin değerini parametre olarak almaktadır. Ardından alınan bilgilere göre değerleri ekrana yazdırmaktadır.
Bu fonksiyonu çağırırken ise LCD_yaz(parametre1, parametre2); şeklinde çağırdık.
Fonksiyonlarımızın aldığı parametre değişkenleri yalnızca fonksiyona ait küme parantezleri içerisinde geçerlidir. Yani analogRead fonksiyonunun parametre değişkeni olan “oku” değişkeni yalnızca analogRead fonksiyonu içerisinde kullanılır.
Şimdi aşağıdaki devreyi kurup yazdığımız kodları yükleyip çalıştıralım. Potansiyometreleri oynadığımızda analog girişten alınan değerlerin değiştiğini LCD ekranda görebilirsiniz.
Böylelikle CCS C dilinde fonksiyonları incelemiş olduk. Eğer bu dersi karışık bulduysanız şöyle özetleyelim:
Parametre almayan geriye değer döndürmeyen fonksiyon
1 2 3 4 5 6 7 |
void fonksiyonum(){ // fonksiyon çağırıldığında çalışacak kodlar } void main(){ fonksiyonum(); // fonksiyonu çağır } |
Parametre almayan geriye int türü değer döndüren fonksiyon
1 2 3 4 5 6 7 8 9 10 |
int fonksiyonum(){ // fonksiyon çağırıldığında çalışacak kodlar int degisken = 15; return degisken; } void main(){ int degisken = fonksiyonum(); // fonksiyonu dönüş değeri ile çağır } |
Parametre alan ancak geriye değer döndürmeyen fonksiyon
1 2 3 4 5 6 7 |
void fonksiyonum(int parametreDegiskeni){ // fonksiyon çağırıldığında çalışacak kodlar } void main(){ fonksiyonum(parametre); // fonksiyonu parametre ile çağır } |
Float türü parametre alan ve geriye int türü değer döndüren fonksiyon
1 2 3 4 5 6 7 8 9 10 |
float fonksiyonum(int parametreDegiskeni){ // fonksiyon çağırıldığında çalışacak kodlar float sonuc = parametreDegiskeni*15.352; // parametreDegiskeni'ni işleme tabi tut return sonuc; // sonuc değişkeni değerini geriye döndür } void main(){ float degisken = fonksiyonum(parametre);// fonksiyonu paramtre ile çağır ve //geriye dönen değeri degiske'e aktar } |