CCS C'de delay_ms sorunu :(

Başlatan stronger_ht, 10 Haziran 2010, 18:06:06

stronger_ht

Arkadaşlar merhabalar hepinize kolay gelsin. Sabahtan beri bir problemim var çözemedim gitti. Sizden yardım bekliyorum. Bu konularda oldukça yeni olduğum için bir çözüm üretemedim...

Sorunum şu...

PIC16f877 ile yaptığım bir projem var. Burada bir giriş portunun değeri 1 olduğunda belirli bir süre bekleterek herhangi bir çıkış portunun aktif olmasını istiyorum. Giriş portunun değeri 1 olduğunda delay_ms(değişken değeri); ile değer veriyorum, ancak 100000 bile versem çok kısa bir süre bekleyip hemen çıkış pini aktif oluyor. Ucunda da bir motor var, motor dönmeye başlıyor. Benim istediğim verdiğim değer kadar bekledikten sonra çıkışın aktif olması.

Sorunumun pic'in ve kristalin çalışma frekansı ile ilgili olduğunu düşünüyorum ama bu sadece benim amatör düşüncem.

Pic 1Mhz de çalışıyor ISIS'te, kristal de 1Mhz, ancak CCS C derleyicisinde ayarlarda #use delay(clock=20000000)  diye geçiyor. Bu kısımlarla ilgili bir hatam var mıdır, ya da bu sorunum başka neden kaynaklanabilir.

Gökhan BEKEN

20000000hz demek 20mhz demektir yani sizin 1mhz kristaliniz olduğuna göre 1*10üzeri6=1000000 olmalıdır.
delay_ms e gelecek olursak eğer bir yanlışım yoksa 255 ten büyük değerlerde sapıtıyordu galiba ama emin değilim.
Özel mesaj okumuyorum, lütfen göndermeyin.

stronger_ht

Peki frenkans olayını düzelttim gibi, şuan kristal + pic + ccs c deki değerlerin hepsi 1mhz ye ayarlı olarak çalışıyor. Buradaki sorun tamam.

delay_ms(); fonsiyonu yerine bekleme olayları için başka ne tarz birşey kullanabilirim. Maksadım butona bastığımda motoru değişkendeki değer kadar bekledikten sonra sürdürmek...

Gökhan BEKEN

#3
hala düzelmedi mi?

isiste pic'e çift tıklayıp default olarak 4mhz gelen değeri 1mhz yaptınız mı?

#include "16f84a.h"     //Mikrodenetleyici seçilir
#fuses XT,NOWDT,NOPROTECT,PUT      //Sigortalar seçilir
#use delay (clock=1000000)

int sure=1000;

void main(void)
{
basla:
output_a(0b00000000);
output_b(0b00000000);
if(input(PIN_b0)==1)
{
   output_a(0b11111111);
   delay_ms(sure);
}   
goto basla;
}


bu komutlarla denedim bendede aynı sorun oldu. delay_ms(); içine değişken girince yanlış çalışıyor.
Değişkensiz delay(1000); girdim tamam ama delay(1001) ve daha fazlasında motor hiç durmuyor.Çözüm olarak üst üste delay(1000); veya delay(sure); yazılabilir
Özel mesaj okumuyorum, lütfen göndermeyin.

Erol YILMAZ

Alıntı yapılan: stronger_ht - 10 Haziran 2010, 18:28:21
...delay_ms(); fonsiyonu yerine bekleme olayları için başka ne tarz birşey kullanabilirim...?

Merhaba,

Tebrikler...
Çok güzel bir soru sormuşsun...
Sadece bu soruya vereceğin cevap ile şu andaki mevcut PROGRAMLAMA ALGORİTMA TEKNİĞİNİ,
A'dan Z'ye değiştirebilirsin.

Öncelikli olarak Super-Loop tekniğini inceleyebilirsin.

Bunu uygulayıp başarılı olduktan sonra da başka teknikler var...

Kolay gelsin...

picmanya

delay_ms(x);
bu komut kullanılırsa işlemci burda ms. cinsinden x süresi bitene kadar çakılı kalır ve daha sonra sıradaki komutları işler yalnızca dış donanım kesmeleri ve iç yazılım kesmeleri inteeruptlu kullanıldığında buna dahil değildir delay_ms(x); fonksiyonu çalışırken oluşacak bir harici ve dahili kesmelerde bunlar inteerupt fonksiyonuyla kullanılıyorsa program ilgili inteerupt fonksiyonu içini işler ve kaldığı yere geri döner bu sizin derleyicide defaultda böyle değilse bu hale getirelebiliyorda olabilir ama mantık budur
şimdi siz ne yapacaksınız!
delay_ms(x); bu fonksiyonu kullanacağınız komut yazım satırında işlemcinin gerçek bağımsız çalışabilen ve ayarlandıkdan sonra çalışması yalnızca işlemcinin kıristal darbelerine bağlı olan timerX'ini gerekli zaman için interruptlu olarak kuracaksınız ve süre sonunda interrupt oluşacak motorunuz çalışacak ve bu interrupt içinde kendi interruptunu ve bir sonraki zaman aynımı kalacak yada daha ne olacak onu yazacaksınız 

siz bu formu incelemiyormusunuz ben bile bunları burdan öğrendim dolu bilgi var böyle.

JKramer

Eskiden hangi değerden sonra sapıttığına bakmıştım, yanlış hatırlamıyorsam (gerçi kaç sürüm değişti arada) 15000'di.

Bunun dışında timer'ları kullanabilirsiniz. Mesela Timer1'i kullanalım. Kullandığınız mikrodenetleyicide Timer1 16 bit'liktir. Yani her bir TIK'da Timer1 bir artacak. Timer1 16 bit'lik olduğundan bu artış 65536'ya kadar sürecek, kesme oluşacak, daha sonra tekrar TIMER_PRELOAD değerinden yukarı doğru saymaya başlayacak. Bir kesmenin ne kadar zamanda oluştuğunu belirledikten sonra, kesme içine bir değişken koyarak istediğimiz gecikmeyi sağlayabiliriz. Zamanlamayı belirlerken ihtiyacımız olan iki şey var; ne kadar zamanda bir TIK oluşturacağız ve TIMER1_PRELOAD değerimiz ne olacak?

Timer'ları ayarlarken iki komutumuz var:

setup_timer_1( TI_DIV_BY_x ); // x=1,2,4,8 olabilir
set_timer1(TIMER1_PRELOAD); // 0<TIMER1_PRELOAD<65536 (Timer 16 bit yerine 8 bit olsaydı 65536 yerinde 256 olacaktı.

0.5 saniyede bir kesme oluşsun diyelim:

TIK=1/(SAAT FREKANSI) * 4 * mode  ( mode, T1_DIV_BY_x'deki x sayısı)
TIK=1/(1*10^6)*4*8 //SAAT FREKANSI 1 MHz, mode da 8 olsun.
TIK=32 us

0.5/(32*10^-6)=15625

Yani Timer1, her 15625 saymanın ardından kesme oluşacak. Kesme 65536'ya ulaştığında oluşacağı için bizim TIMER1_PRELOAD değerimiz:

65536-15625=49911

Toparlayalım;

setup_timer_1( T1_EXTERNAL | TI_DIV_BY_8 ); //Dahili clock kullanırsak T1_INTERNAL
set_timer1(49911);

Erol YILMAZ

Benim bildiğim 4 adet yöntem var geciktirme için...

Kısaca geciktirme yöntemleri :

1)  x adet timer kesmesi sonra ? ( RTOS larda çokça kullanılır... iyi yazılımcılar da genelde bunu kullanıyor... )
2)  x adet döngü sonra... ( yerine göre uygun )
3)  Timer int'i ayarlayıp kesme oluşunca... ( kısa zaman gecikmelerinde... )
4)  x komut sonra... ( acemi işi delay_ms() ler bu şekilde çalışıyor )



5. yi bilen varsa merakla dinleriz :)

SERRO EFE

#8
ben genelde şu şekilde kullanıyorum

dim sayac(x) as byte
dim istenen_süre(x) as byte
.
.
.
timer_kesmesi:
for x = 0 to y
incr sayac_gecikme(x)
next

for x = 0 to y
if sayac_gecikme(x)= istenen_süre(x)
İŞLEM
endif
next
return

bu yapıyı  enson 8 giriş 5 çıkış için kullanmıştım

picmanya

5. yöntem
örnek kod falan istemeyin yok
16 ve 32 bit işlemcilerin C derleyicilerinin bazılarında rastlıyorum
işlemcinin programı yürüttüğü ana saat darbeleri otomatik donanımsal bir yapıyla kontrol edilebiliyor ve burdan iş gördürülüyor.wdt benzeri ama daha farklı bir çalışma yapıyor

acemi2010

Alıntı yapılan: picmanya - 11 Haziran 2010, 15:16:40
5. yöntem
örnek kod falan istemeyin yok
16 ve 32 bit işlemcilerin C derleyicilerinin bazılarında rastlıyorum
işlemcinin programı yürüttüğü ana saat darbeleri otomatik donanımsal bir yapıyla kontrol edilebiliyor ve burdan iş gördürülüyor.wdt benzeri ama daha farklı bir çalışma yapıyor

6ıncı yöntem olurmu hiç emin değilim; ama harici interrupt pinine bağlanacak paralel bir RC devresi  (acemice olsa da) işe yarayabilir belki.

Timuçin

muhittin_kaplan

10 ms beklemek için nasıl timer ve diğerleri kullanılır ? Meşhur 5 adet içinde birer algoritma çıkartımısınız.