CCS-C ile PIC Programlama, Gecikme Fonksiyonlarının Kullanımı

CCS-C ile PIC için yazacağınız kodların hemen hemen hepsinde gecikme (Delay) sürelerine ihtiyacınız olacak. Bu süreleri ede etmek için iki seçeneğiniz var. Birincisi PIC içerisindeki Timer’ları kullanmak. Bunun için bir dizi konfigürasyonu, kullanacağınız CPU frekansına göre ayarlamak ve yine bununla ilgili kodları yazmanız gerekiyor. İkinci yöntem ise sadece gecikme süresi oluştumak için boş döngüler kullanmak.
Örneğin 1 ms (Mili Saniye) sürecek, içerisinde döngü olan bir fonksiyon yazabilir ve diğer süreleride 1 ms’nin katları olarak bu fonksiyonu o kadar çağırarak elde edersiniz. Böyle bir durumda da yine denetleyicinin çalıştırılacağı saat frekansına göre döngünüzü hesaplamanız gerekiyor.

Peki bunlarla uğraşmak istemiyorsak ne yapacağız? Cevabı çok basit, üçüncü bir yöntem var :)


CCS-C’nin gecikme süreleri elde etmek için bize sunduğu hazır fonksiyonları kullanacağız. Derleyici bu iş için bize üç adet hazır fonskiyon sunuyor.

delay_cycles()
delay_us()
delay_ms()

Bu üç fonsksiyondan herhangi biri kullanılacağı zaman. #use delay direktifi ile işlemcinin saat frekansının belirtilmesi gerekiyor. Örneğin denetleyicide 4 Mhz (Mega Hertz) kristal kullanmışsak

#use delay(clock=4000000) şeklinde

Eğer WatchDog Timer kullanmışsak ve gecikme sürelerimizi elde ederken watchdog timer’ın taşmasını istemiyorsak

#use delay(clock=4000000,restart_wdt) şeklinde tanımlama yapmalıyız.

Yeri gelmişken #use delay direktifi ile ilgili daha önce anlatmadığım ayarlardan bahsedeyim biraz

Saat frekansını şu şekillerde de belirtebiliriz

#use delay(clock = 4, 000, 000)
#use delay(clock = 4M)
#use delay(clock = 4M, oscillator) // XT Konfigürasyon biti set edilir
#use delay(oscillator=4M) // Yukarıdaki ifade ile aynı
#use delay(clock=40M,oscillator=10M) // krsital 10 MHZ ama PLL açık H4 biti set edilir

Konfigürasyon bitlerini #fuse direktifi ile kendinizin de tanımlayabileceğinizi unutmayın.

Şimdi bu üç fonksiyonun ne işe yaradığını anlatmadan önce “Instruction Time” denilen komut işletme süresinin ne olduğuna bir bakalım.
PIC denetleyicilerinin herhangi bir komutu işletmek için gerek duyduğu zamana instruction time denir.

Instruction Time (IT) = 4 x (1/Saat frekansı) formülü ile hesaplanabilir

4 Mhz Saat frekansı için
IT = 4 x (1/4000000) = 0,000001sn = 1 us (Mikro Saniye, saniyenin Milyonda biri)

20 Mhz Saat frekansı için
IT = 4 x (1/20000000) = 0,0000002 sn = 200 ns (Nano Saniye, saniyenin Milyarda biri)

delay_cycles()

1-255 arası değer alan bu fonksiyon belirtilen sayı kadar Instruction Time gecikmesi sağlar. Parametre olarak sabit sayı verilebileceği gibi 8 bitlik değişken de verilebilir

int gecikme;
gecikme = 10;
delay_cycles(5) // 5 instruction time kadar gecikme üretir
delay_cycles(gecikme) // 10 instruction time kadar gecikme üretir
4 mhz Saat frekansı için ( IT = 1 us )
delay_cycles(100); komutu 100 us Gecikme oluşturur

20 Mhz Saat frekansı için ( IT = 200 ns )
delay_cycles(100); komutu 20 us Gecikme oluşturur

delay_us()

Mikro Saniye cinsinden gecikme süresi elde etmek için kullanılan bu fonksiyon parametre olarak 0-65535 arası bir değer alır. Bu sabit bir değer olabileceği gibi değişken de olabilir

4 Mhz saat frekansı için
delay_us(100); 100 us lik gecikme üretir

20 Mhz saat frekansı için
delay_us(100); 100 us'lik gecikme üretir
delay_us(10000); 10000 us = 10ms Gecikme üretir

Gördüğünüz gibi bu fonksiyonda saat frekansı ne olursa olsun derleyici buna göre kendini ayarlayarak istenilen süreyi oluşturur.

delay_ms()

Mili Saniye cinsinden gecikme süresi elde etmek için kullanılan bu fonksiyon parametre olarak 0-65535 arası bir değer alır. Bu sabit bir değer olabileceği gibi değişken de olabilir

4 Mhz saat frekansı için
delay_ms(50); 50 ms'lik gecikme üretir

20 Mhz saat frekansı için
delay_ms(50); 50 ms'lik gecikme üretir
delay_ms(1000); 1000 ms = 1 sn Gecikme üretir

Gördüğünüz gibi bu fonksiyonda da saat frekansı ne olursa olsun derleyici buna göre kendini ayarlayarak istenilen süreyi oluşturur.

Eğer Kesme kullanıyorsanız bu fonksiyonlardan elde edeceğiniz gecikme süreleri tam olarak doğru olmayabilir. Çünkü bu gecikmeler üretilirken program Kesme rutinine girebilir ve orada bir miktar zaman geçeceğinden süreler tam olarak tutmaz. Çok hassas gecikmeler elde etmek için Timer’ları kullanmak gerekir.

CCS-C ile PIC Programlama, Gecikme Fonksiyonlarının Kullanımı yazısı için 23 yorum yapıldı

  1. osman says:

    siteyi devamlı takip ediyorum… CCS C ile Pic Programla adlı bir kitapda; gecikme fonksiyonlarındaki değerin değişken olması durumunda 0-255 arası değer alabileceği yazıyordu.. Bunla ilgili bir açıklama yapabilir misin? yani int16 şeklindeki bir değişkenle kullanabilir miyiz?

  2. Emrah AYDIN says:

    @osman
    delay_cycles() fonksiyonu için dege 1-255 arası olabilir dolayısıyla int8 bir değişken bu fonksiyona geçilebilir. delay_us() ile delay_ms() fonksiyonlarına ise int16 geçilebilir.
    Derleyicinin eski versiyonlarında bir Bug’tan(Hata) dolayı delay_us() ve delay_ms() fonksiyonlarına geçilen 16 bit değişkenlerin high byte’ı işleme alınmıyordu. Yeni versiyonlarda bu hata giderildiği için bu fonksiyonlara int16 değişken geçilebilir.

  3. FxDev says:

    En sevdiğim fonksiyonlar bunlar =D
    Yerim ben onları XD

  4. Emrah AYDIN says:

    @FxDev
    Afiyet olsun :)
    CCS-C nin olmazsa olmazları bunlar, büyük kolaylık :)

  5. İnternet olmaması sebebiyle yazıyı indirip evde okudum.Güzel olmuş her zamanki gibi.Şu kesme denilen şeyleri baya merak ettim.En kısa zamanda tanıştırmanız dileğimle hocam.
    İyi günler.

  6. Emrah AYDIN says:

    Bu aralar biraz rölantideyim Hasan, sanırım sıradaki 2. veya 3. yazıda kesmeleri anlatacağım. Kolay Gelsin

  7. mertikk says:

    Selamlar gerçekten çok başarılı dersler, takip ediyorum sürekli.

    Bir konuda takıldım, buradan soruyor, cevabının başka arkadaşlara da yardımcı olmasını umuyorum.

    sadece pic kullanarak günde 6 saatte bir 15 sn boyunca bir ledi nasıl çalıştırabilirim?

  8. [...] 12- Gecikme (Delay) Fonksiyonları ve Kullanımı [...]

  9. Emrah AYDIN says:

    @mertikk

    #include
    #use delay(clock=4000000)
    #fuses INTRC_IO, XT, PUT, PROTECT, NOMCLR, NOWDT

    #define LED PIN_B0

    void main(void)
    {
    int dakika,saat,saniye;
    while(TRUE)
    {

    for( saat=0; saat < 6; ++saat ) // 6 saatlik döngü
    {
    for( dakika=0; dakika < 60; ++dakika ) // 1 saatlik döngü
    {
    for( saniye=0; saniye < 60; ++saniye ) // 1 dakikalık döngü
    {
    delay_ms(1000); // 1 saniyelik süre
    }
    }
    }
    output_high(LED); // LEd’i yak
    delay_ms(15000); // 15 sn bekle
    output_low(LED); // ledi söndür

    }

    }

    Yukarıdaki kod Port B0′a bağlı ledi 6 saatte bir 15 sn yakar. 16f628′in dahili 4 mhz osilatörü kullanıldı. Yanlız bu süreler biraz esnek olacaktır.
    Kolay Gelsin

  10. burak barış says:

    s.a java programnı yüklüyom ancak hata veriyo şöle:

    yayımcı doğrulanamıyor.Bu yazılımı çalıştırmak istediğinizden eminmisiniz.nie acba bazı sitelerde de böle sorular baktım ama sonuç yok yardımcı olabilrmisiniz.tşk ederim.

  11. Emrah AYDIN says:

    @burak
    http://www.mozilla-europe.org/tr/firefox/
    bu adresten firefox 3.0′ı indir bilgisayarına kur bunu kullan internet explorer yerine.

  12. mertikk says:

    Sayın Emrah AYDIN,

    Yazdığınız kod için, ve özellikle zaman ayırdığınız için çok teşekkürler.

    Saygılarımla.

  13. Emrah AYDIN says:

    @mertikk
    Eyvallah

  14. Erol says:

    delay_ms(1);
    yazdığımızda CCS kesmeleri kapatıyor mu?
    Kapatmazsa zaman doğruluğu olmayacak, Kapatırsa kesmeler kaçırılacak.
    Nedir bu işin çözümü? :)
    Öncelikle şunu söylemek isterim, bu tarz programcılığı ancak amatör seviyede olanlar yapar, Delay_ms gibi bir fonksiyon Profesyonel Gömülü programcılıkta kabul edilebilecek bir fonksiyon değildir. Program tam olarak kesintiye uğratılamaz ! Peki ne yapabiliriz diye sorun lütfen :)
    Ben de bi soru sorayım, 7 tane led olsun, bunlar 100 ms, 120, 150, 180, 250, 335, 650 ms aralıklarla yanıp sönsün, Bu mantıkla bunu yapabilirmisiniz ?

  15. Emrah AYDIN says:

    @erol
    1. Bu işi yapmak için tek yol delay fonksiyonlarını kullanmaktır demedik bu yazımızın başında bu bir. Yazının başını iyi okuyun lütfen
    2. Olayın profesyonellikle alakası yok, tamamen sizin ihtiyacınıza bağlı bi durum çok hassas sürelere ihtiyacınız yoksa zamandan kzanmak için bu fonksiyonları kullanabilirsiniz. Yada örneğin dimmer tetiklemesi gibi hassas gecikmelerinizi timer kullanarak halledebilirsiniz.
    3. Bahsettiğiniz olaya gelince tek bir timer interrupt ile rahatlıkla yapılabilir. Hatta delay_fonksiyonları ile de yapılabilir aşağıdaki kod gibi MESELA

    int l1,l2,l3,l4,l5,l6,l7;

    l1=l2=l3=l4=l5=l6=l7=0;
    while(1) {
    delay_ms(1);
    if(++l1 == 100) { led 1 toggle yap l1 = 0 yap}
    if(++l2 == 120) { led 2 toggle yap l2 = 0 yap}
    if(++l3 == 150) { led 3 toggle yap l3 = 0 yap}
    if(++l4 == 180) { led 4 toggle yap l4 = 0 yap}
    if(++l5 == 250) { led 5 toggle yap l5 = 0 yap}
    if(++l6 == 335) { led 6 toggle yap l6 = 0 yap}
    if(++l7 == 650) { led 7 toggle yap l7 = 0 yap}
    }
    Şimdi siz diyceksiniz bu süreler hassas olumaz? olsa ne olur olmasa ne olur altı üstü led yakıyorum. ayrıyeten üretilen koddaki instruction sayısına bakılarak döngü süresi cok daha hassas ayarlanabilir

    Ayrıyeten CCS-C nin RTOS desteği de kullanılabilir bu dediğiniz uygulama için çok ta şık olur.

    Sizin mantığınızda olan arkadaşlara söylediğimi sizede söylüyorom;

    Siteniz varsa ve bu konuyla ilgili makaleniz de varsa buradan link vereyim.
    Siteniz yok ise bir makale hazırlayın sizin adınıza yayınlayayım.

  16. elseus says:

    Hocam sen onlara kulak asma.hem kimseye faydalı bir paylaşım yapmazlar hemde yapanlara uklalık yaparlar.Biz senin açıklamaların sayesinde herkesin kabaca atlayıp geçtiği konular hakkında detayları çözüp anlar olduk…CCS C konusunda kitap yazıp satanlar bile karşısındakinin anlayabileceği şekilde anlatmayı beceremezken sen herkesin anlayabileceği şekilde anlatıyorsun.bundan ötürü şahsım adına teşekkür ediyorum..

  17. Emrah AYDIN says:

    @elseus
    Her türlü eleştiriye açığız arkadaş bir şeyler sormuşbizde cevabını yazdık. Bu arada gönderdiğin maili okudum ve cevap yazdım haberin olsun.

  18. elseus says:

    Hocam detayları anlatan bir mail yolladım .ama sana ulaşıp ulaşmadığından emin değilim.eğer ulaşmadıysa tekrar yollıyayım.saygılar..

  19. yaren says:

    hocam iyi günler.
    #include “F:\PIC PROGRAM\16f84 brenner\main.h”
    #include
    #use delay(clock=4000000)
    #fuses NOWDT,XT, NOPUT, NOPROTECT
    konfigürasyon ayarlarını yaptığımda
    main.h sekmesinde
    #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
    hata gösteriyor. düzeltmeyi hangi sekmede yapmalıyım

    basit bir uygulama yapacaktım 16f84 için ihtiyacım olan
    konfigürasyon ayarlarını yazabilirmisiniz.
    16f84 de

  20. Emrah AYDIN says:

    #include
    yazdığın kodda bu şekilde boş bir satır var.. hatayı buna veriyor olabilir hatayı..
    16F84 için #fuses XT,NOWDT,PUT,NOPROTECT yeterli…

  21. seyfettin kazanir says:

    hocam güzel çalışma olmuş bu tarihten itibaren takip ediyorum.. zaten fxdev de buralarda takıldığına göre bizde gerilerde kalmayalim değilmi ustat :)

  22. Emrah AYDIN says:

    @seyfettin, çalışma güzel oldu ama gerisini getiremiyorum bir türlü :) bi konsantre olamadım gitti…

  23. Osman says:

    Hocam iyi günler paylaşımlarınızı gerçekten cok begendm :)
    sormak istedgim birşey var.pic c complier kullanıyorum.bir iş üzerinde çalışıyorm 16f84a ile kontrol edeceğim bi sistem var.sensör 4 sn kesintisiz görürse sistem duracak.ama mesela 2 sn, 3sn 3.5sn gibi zamanlar görürse çıkışın on olması devam edecek.programı yazdım fakat karşılastıgım sorun: mesela 2sn gördü giriş kesildi daha sonra 3 sn gördü.çıkışta işlemi 5 sn görmüş gibi yapıyo.yani kısaca sinyal girdigi süreleri hafızasında topluyo.buda benim istedgim 4sn’yi yakalayamama sebep oluyo.yardım ederseniz cok sevinirim.kendi yazdıgım programda şu;

    #include
    #fuses xt,wdt,put,noprotect
    #byte port_a=5
    #byte port_b=6
    #use delay(clock=4000000,restart_wdt)
    #define d input(pin_a0)
    #define b port_b
    void main() {

    set_tris_a(0xff);
    set_tris_b(0×00);
    while(1){
    port_b=0xff;

    if(input(pin_a0)==1 && b==0xff)

    delay_ms(5000);
    port_b=0×00;

    if(input(pin_a0)==0 && b==0×00)

    delay_ms(5000);
    port_b=0xff;

    }}

    pin_a0=sensör
    out_b0=çıkış

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>