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.


Bu yazı için 21 yorum yapıldı
August 30th, 2008
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?
August 31st, 2008
@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.
August 31st, 2008
En sevdiğim fonksiyonlar bunlar =D
Yerim ben onları XD
August 31st, 2008
@FxDev
Afiyet olsun :)
CCS-C nin olmazsa olmazları bunlar, büyük kolaylık :)
September 10th, 2008
İ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.
September 10th, 2008
Bu aralar biraz rölantideyim Hasan, sanırım sıradaki 2. veya 3. yazıda kesmeleri anlatacağım. Kolay Gelsin
September 10th, 2008
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?
September 10th, 2008
@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
September 13th, 2008
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.
September 13th, 2008
@burak
http://www.mozilla-europe.org/tr/firefox/
bu adresten firefox 3.0′ı indir bilgisayarına kur bunu kullan internet explorer yerine.
September 16th, 2008
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.
September 16th, 2008
@mertikk
Eyvallah
October 24th, 2008
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 ?
October 24th, 2008
@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.
October 24th, 2008
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..
October 24th, 2008
@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.
October 26th, 2008
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..
August 10th, 2009
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
August 10th, 2009
#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…
September 4th, 2009
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 :)
September 4th, 2009
@seyfettin, çalışma güzel oldu ama gerisini getiremiyorum bir türlü :) bi konsantre olamadım gitti…
Geri izlemeler