Haberler:

Forum kuralları güncellendi LÜTFEN  okuyunuz:  https://bit.ly/2IjR3ME

Ana Menü

CCS INTERRUPT HATASI

Başlatan kalman, 15 Haziran 2005, 20:05:35

kalman

CCS ile ilgili bir  HATA  

Diyelimki siz Interrupt_RB ile portB RB4-7 de oluşan bir değişiklikte
RB1 pinindeki LED i yakıyorsunuz bunu bır ISR ile gerçekleştirdiğinizde
gayet güzel çalışıyor ve Ana Programda ise LED tekrar sönuyor  ;)

Fakat LED i PortA RA1 bağlandığında  program bir türlü  ISR i terketmiyor
ve Ana Programda ise LED sönmeli fakat sönmüyor daha iyi anlanması için
kodları ekliyorum




#include "interrupt.h"

#define LED PIN_B1 // sorun burada bunu A1 yaptığınızda Çalışmıyor


#int_RB // Interrupt
LED_YAK()
{
disable_interrupts(GLOBAL);
output_high(LED);
delay_ms(500);
enable_interrupts(GLOBAL);
}



void main() {

set_tris_a(0b00000);
set_tris_b(0b00110000); // RB4 ve RB5 giris

setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
ext_int_edge(L_TO_H);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);





while (1)
{
output_low(LED); //LED söndür
}

}



Bununla ilgili önerileriniz  Acaba bu CCS bir hatası olabilirmi??

Saygılarımla

ahmetu

elbette olmaz pic ilk çalışmada PORTA'yı analog atar bunu digital'e çevirmen gerekli

setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);



ayrıca ISR içinden diğer ISR'ler yada GLOBAL kapatılıp açılmaz.

kalman

@Ahmetu cevap verdiğin için teşekkürler

devrede kullanılan PIC 16f84, bildiğim kadarıyla bunlarda bütün portlar zaten digital olarak çalışmakta.

ISR içinde olan global açmayı sildim sonuç yine değişmedi

Yanlış anlaşılmasın program ilk çalıştığında led sönük sonra ISR gereği Led
yanıyor fakat sonra ISRden çıkıp Led sönmüyor halbuki bu ccs c tarafından otomatik yapıldığı yazılıyor fakat bu portA da olmuyor

İsteyen arkadaşlar deneyebilirler bence bu ccs den kaynaklanıyor
acaba INTCON registere manual ulaşabilinirmi  :roll:  :roll:
LST dosyasındanda pek bir şey belli olmuyor

Örneklerdede hep portB kullanılmış bu durumda program zaten çalışıyor
portA da ise durum farklı ISR den normal programa bir türlü gidilmiyor
Arkadaşlar bu konuda  görüşlerinizi bekliyorum

saygılarımla

z

Program asm halini de koyabilirmisin? C derleyici int rutinini terkederken neler yapiyor oran bakariz.

INTCON regi int dan cikarken yeniden init etmeyi dene.

(INT rutini icinde 500 ms  bekleme yapmak bana biraz ters geliyor.)
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erkan Gench

programı denedim dediğiniz gibi yapıyor. rb intterruptu yerine ext interruptu deneyince bir sorun olmadığını gördüm. eğer rb'yi kullanmak zorunda değilseniz ext (b0) interruptunu kullanabilirsiniz. zaten bu tip sorunlar ccs için olağan.

açıkçası kim ne derse desin ccs amatör bir compiler zaten c ilede çokta yakından alakası yok. adamlar c adı altında yeni bir dil yapmışlar sanki. zaten ccs'nin kendi forumunda da dalga geçiyorlardı eğer yeni bir optimizasyon yapıldı diye duyuru yapılırsa kesin bir-iki gün sonra yeni optimizasyon için düzeltme yapıldığı haberi geliyor diye.

herhalde en sık update'i çıkan compiler budur.

tabi benim canımı asıl sıkan şey büyük bir projenin tam ortasında olmayacak hatalar yapmaya başlaması ve sonra işin tamamen çığrından çıkması. en başta işler güzel giderken proje büyüdükçe sorunlar çıkarmaya başladı. bundan dolayı bir ay yeni compiler aramakla geçti. asıl önemlisi bir sürü rezillik çektim. tam projenin sonuna geldik bitti bitiyor derken herkes birşey beklerken kendinizi bu halde bulduğunuzu düşünün.

şimdi microchip c18 kullanıyorum ve çok memnunum eğer gerçek c tadı yaşamak istiyorsanız kesinlikle tavsiye ederim. ayrıca hiç sorun yaşamadım şimdiye kadar. tabi sadece 18 serisi picleri destekliyor. aslında bence 16 serisi picler piyasadan kalkmalı artık ama.
Zorluklar, zamanında yapmamız gerekip de yapmadığımız kolay şeylerin birikmesiyle oluşur. Henry Ford ----------- Ya Rabbi Filistin'deki ve dünyanın her tarafındaki Müslüman kardeşlerime yardım et.

ahmetu

Alıntı yapılan: "bunalmis"(INT rutini icinde 500 ms  bekleme yapmak bana biraz ters geliyor.)

doğru usta sorunda oradan zaten delay esnasında sürekli INT aktif oluyor


16f84 kullanığınızı bilmiyordum neyse kurallara uyunca herşey mümkün işte çalışan kod;

#include <16F84.h>
#fuses NOWDT,HS,NOPUT,NOPROTECT
#use delay(clock=4000000,RESTART_WDT)

#define LED PIN_A1


BOOLEAN ledyak=FALSE;


void ledkontrol() {
   if (ledyak)
   {
      ledyak = FALSE;
      output_high(LED); //LED yak
      delay_ms(500);
   }
   output_low(LED);     //LED söndür
}


#int_RB
void RB_ISR() {
   if (input_b() && 15)
      ledyak = TRUE;
   else
      ledyak = FALSE;
   ledkontrol();
}


void main() {
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   set_tris_a(0);
   set_tris_b(0b00110000); // RB4 ve RB5 giris
   ext_int_edge(L_TO_H);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);

   while(1);
}

Petek

Arkadaşım,
interrupt rutininde işin bitince flagi resetleyerek çıkman lazım. Yoksa tam çıkıyorum derken flag set edildiği için tekrar interrupta dönersin. Yani sonsuz döngüye girmişsin.

Şunu programına ekle.
#bit rbif=0x8b.0



interruptın sonunda

rbif=0;


CCS bana kalırsa son derece mükemmel bir dil. ANSI C olmamış olması beni etkilemiyor. 877 üzerinde %98 kod alanına sığacak son derece karmaşık programları bile mükemmel bir şekilde derliyor. Optimizasyonu harika. Tek eksikliği program parçalarını 2 K page alanına tam sığdırmaya çalışıyor. Bunu yapamadığında out of rom hatası veriyor. Bunu da altprogramların bazılarının başına "#separate" koyarak çözüyorum. Stack kritik olunca biraz tecrübe ile sorunu başka şekilde çözüyorum.

CCS en mükemmeli demiyorum ama neyi nasıl yaptığını bilirseniz çok mükemmeldir derim.
“Önyargıları yıkmak atomu parçalamaktan zordur” A.Einstein

Erkan Gench

Alıntı yapılan: "Petek"CCS bana kalırsa son derece mükemmel bir dil.

ben yazdıklarım başıma gelmeden önce 2 seneden fazla ccs kullandım ve aynen böyle düşünüyordum. ccs ile 10'a yakın büyük sayılabilecek proje yaptım küçükleri saymıyorum. fakat bu söylediklerim başıma gelince ve c18 kullanmaya başlayınca aklım başıma geldi. insan iyisini görmeden kötünün ne olduğunu anlayamıyor. sizde zor yoldan öğrenmeyin derim burada tecrübe varken. zaten bu olaylar başıma gelince yaptığım araştırmalarda dünyada bir çok kişinin benim gibi düşündüğünüde gördüm. bu arada benim söylediğim şey ccs'nin amatör olduğu prof. olarak kullanmıyacak, amacı ufak tefek işler yapmak olan kimselere lafım yok. (yanlış anlaşılmasın bu yazdıklarım size değil sayın petek ben genel anlamda yazıyorum)

ccs küçük projeler için başarılı ufak tefek işlerde hala kullanıyorum fakat büyük işlere asla girmem.

interruptun başında flagı reset etmenize gerek yok çünkü 16f84'te int içerisinde yeni int gelirse işlemler bitirlmeden çıkılmaz. sonundada resetlemenize gerek yok çünkü ccs bunu otomatik yapıyor zaten (lst dosyasına bakın.)

ayrıca int içinde delay yapmak pratikte kesinlikle kullanılacak bir şey değil int rutinleri olabildiğince kısa olmalıdır. çünkü int içindeyken yeni int gelirse uygun flag set edilir ve mevcut int'in işini bitirmesi beklenir. işi biter bitmez yeni int gerçekleştirilir. fakat işi bitmeden önce bir int daha gelirse bu durumda flag zaten set olduğundan bu yeni int kaybolacaktır.

ahmetu hocam int içinde delay olmasından kaynaklandığını söylemişsiniz sorunun. halbuki yazdığınız program da int içinde delay yapıyor. int içinden çağırdığınız fonksiyon yine int içinde sayılır.

bundan da öte ccs'de böyle basit programlarda trislerle uğraşmanıza gerek yok. siz output_high dediğiniz de yazdığınız pinin trisi otomatik olarak output yapılır. bunu kapatmak için özellikle bir komut yazmanız lazım (fast io). birde ext_int_edge fonksiyonu rb0 interruptunun hangi kenarda gerçekleşeceğini belirler rb interruptu ile alakası yoktur.
Zorluklar, zamanında yapmamız gerekip de yapmadığımız kolay şeylerin birikmesiyle oluşur. Henry Ford ----------- Ya Rabbi Filistin'deki ve dünyanın her tarafındaki Müslüman kardeşlerime yardım et.

kalman

@Ahmetu verdiğin kod çalışıyor fakat RB4 ve RB5 aynı anda Low olduğunda ISRe atlama yapmıyor dolayısıyla ISR tam olarak görev yapmıyor uğraştığın ve yazdığın cevaplar için çok teşekkürler fakat problem hala çözülmüş değil

@Petek yazdığın işlemi yaptım sonuç degişmedi ıntcon.0  ISRden sonra değişmiyor denedim. Tam programı verebilirmisin ayrıca cevabın için
teşekkürler :idea:  :idea:

CCS C böylesine ufak programda sorun çıkarmasına  pek anlam veremedim  belkide Erkan gench haklı

Arkadaşlar bu bir Bug mu sizce   CCs C programlayan arkadaşlar bunu sadece benmi farkettim yoksa sizde böyle sorunlar yaşadınızmı ??

:cry:  :cry:

Görüşlerinizi bekliyorum

saygılarımla

Erkan Gench

programın olması gereken şekli şöyle:

#define LED PIN_a1 // sorun burada bunu A1 yaptığınızda Çalışmıyor
int1 ledyak=0;

#int_ext // Interrupt
LED_YAK()
{
   ledyak=1;
}



void main() {

   setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
   enable_interrupts(INT_ext);
   enable_interrupts(GLOBAL);

   while (1)
   {
      output_high(led);
      if(ledyak)
      {
         output_low(LED); //LED söndür
         delay_ms(500);
         ledyak=0;

      }
   }

}


fakat bu int_ext için yazılmış hali ayrıca normalde yanan led butona basınca söndürülüyor. rb int'ini daha önce hiç kullanmadım. açıkçası hiç gereği olmadı. int'i rb yapınca kod çalışmıyor neden olduğunu bilmiyorum belki ccs'den belkide benim rb int'i konusundaki tecrübesizliğimden.  fakat interrupt kullanma mantığınız bu olmalı yani int oldukça kısa olmalı uzun işleri ana programa yaptırmalısınız.
Zorluklar, zamanında yapmamız gerekip de yapmadığımız kolay şeylerin birikmesiyle oluşur. Henry Ford ----------- Ya Rabbi Filistin'deki ve dünyanın her tarafındaki Müslüman kardeşlerime yardım et.

Petek

Alıntı yapılan: "Erkan Gench"
Alıntı yapılan: "Petek"CCS bana kalırsa son derece mükemmel bir dil.

ben yazdıklarım başıma gelmeden önce 2 seneden fazla ccs kullandım ve aynen böyle düşünüyordum. ccs ile 10'a yakın büyük sayılabilecek proje yaptım küçükleri saymıyorum. fakat bu söylediklerim başıma gelince ve c18 kullanmaya başlayınca aklım başıma geldi. insan iyisini görmeden kötünün ne olduğunu anlayamıyor. sizde zor yoldan öğrenmeyin derim burada tecrübe varken. zaten bu olaylar başıma gelince yaptığım araştırmalarda dünyada bir çok kişinin benim gibi düşündüğünüde gördüm. bu arada benim söylediğim şey ccs'nin amatör olduğu prof. olarak kullanmıyacak, amacı ufak tefek işler yapmak olan kimselere lafım yok. (yanlış anlaşılmasın bu yazdıklarım size değil sayın petek ben genel anlamda yazıyorum)

ccs küçük projeler için başarılı ufak tefek işlerde hala kullanıyorum fakat büyük işlere asla girmem.

interruptun başında flagı reset etmenize gerek yok çünkü 16f84'te int içerisinde yeni int gelirse işlemler bitirlmeden çıkılmaz. sonundada resetlemenize gerek yok çünkü ccs bunu otomatik yapıyor zaten (lst dosyasına bakın.)

Erkan Bey, 2 yıl kadar Jal ile programlamadan sonra CCS gözüme son derece mükemmel göründü. Jal de pek çok şeyi assembler da yapıyormuşsunuz gibi yapmanız gerekiyor. Bu alışkanlıktan dolayı olsa gerek flagi resetlemek gerektiğinden bahsetmiştim. Sonradan farkına vardım tabi. CCS donanım hakkında çok fazla bilgisi olmayanlar için geliştirilmiş ve pek çok şeyi otomatik hallediyor. Geçenlerde 12F675 için program yazmıştım. OSCCAL değerini atamak için kodlar ekledim. Sonradan LST den baktım ki CCS zaten onu (ve portu analog yada dijital nasıl kullanmış isek) ona göre kodları eklemiş. IO portları için de oldukça kullanışlı compiler direktifleri var. Hata yapmak gerçekten zor. Eski versiyonlarının birinde stack overflow olmuş fakat hata vermemiş. Program 0 stack seviyesine dönmemişti. Onu da başka türlü halletmiştim. Ama neredeyse her gün yeni versiyon çıkarttıkları için bu sorunların hallolduğunu sanıyorum. Bir versiyon sonrasında bile optimizasyonda baya iyileştirmeler görmüştüm. Out of rom hatasını hiç sevmedim. Değişik yollardan çözüyorum ama açık söylemek gerekirse oldukça saçma bir mantıkla bu hata çıkıyor. Düzeltirler diye bekledim ama bu ilk versiyonlarda bile var olan birşeymiş. Gülün dikeni gibi yani.

Erkan Bey, sizin CCS de karşılaştığınız sorunlar neler paylaşırsanız sevinirim.

C18 derleyicisi bende de var (updateleri de var). Sorun elimde numune 2 adet 452 ve 2 adet 242 var. Bunlarla henüz ciddi anlamda uğraşamadım. Elimde daha önceden yaptığım projeler vardı ve elimdeki eski işlemcileri de eritmem gerekiyordu. O nedenle CCS de devam ediyorum. 18 serisine geçmeyi çok istiyorum ama biraz da maliyetleri düşsün diye bekliyorum. Yoksa benim en büyük sıkıntım 16 serisindeki yetersiz stack alanı. 8 stack alanında çok fazla menü derinliği oluşturamıyorum. Menünün en derin kısımlarında ( ne güzel bir tabir oldu :) sub program kullanamıyorum. interrupt rutinlerinde stack tüketecek işlem yapamıyorum. LCD ve i2c rutinlerini bile 3 stack götürecek şekilde yeniden düzenledim. Yani baya göbek attım.

Kalman, Programı ISIS üzerinde debug ederek hatanın ne olduğu bulunabilirsin. Coff dosyasını ISISte yüklemen yeterli. Debug edip, adım adım programı çalıştır. Program akışını izle nerede takıldığını görürsün.
“Önyargıları yıkmak atomu parçalamaktan zordur” A.Einstein

SpeedyX

Tartışmayı alevlendirmek için int içerisindeki kod kısa olmalı kesinlikle delay olmamalıya karşı çıkayım.

mesela rs232 interrupt ı düşünün, bir devre var ve bu mesela triyak ile lamba kontrol ediyor, normalde hiç uart ile uğraşmıyor ve zero cross a göre lambayı tetikliyor falan...
ama uart dan veri geldiğinde bir interrupt oluşuyor ve program int alt programına gidiyor, orada delay kullanarak veri alış verişi yapıyor, gelen verilerin doğruluğunu kontrol ederek karşı tarafa okey sinyali yolluyor.
bu şekilde çalışan yüzlerce uygulama var ve aslında buradaki sözünüz doğru ama onu şu şekilde değiştirmeliyiz diye düşünüyorum;
Alıntı Yapayrıca int içinde delay yapmak pratikte kesinlikle kullanılacak bir şey değil int rutinleri olabildiğince kısa olmalıdır. çünkü int içindeyken yeni int gelirse uygun flag set edilir ve mevcut int'in işini bitirmesi beklenir.

Eğer int alt programı içerisinde int i kapatıp, program bitiminde tekrar açmıyor ise int kodu oldukça kısa olmalıdır yoksa isr içerisinde iken yeni bir int geldiğinde o veri kaybolacaktır.

Bu şekilde olursa daha iyi olacağı kanısındayım.
CCS çok iyi değildir demişsiniz, peki hangisi gerçekten iyidir (asm hariç)?

Petek

Alıntı yapılan: "SpeedyX"
Eğer int alt programı içerisinde int i kapatıp, program bitiminde tekrar açmıyor ise int kodu oldukça kısa olmalıdır yoksa isr içerisinde iken yeni bir int geldiğinde o veri kaybolacaktır.

Bu şekilde olursa daha iyi olacağı kanısındayım.
CCS çok iyi değildir demişsiniz, peki hangisi gerçekten iyidir (asm hariç)?

Hocam, int geldiğinde interrupta gidiyorsun ya, zaten o arada GIE biti 0 oluyor. Assemblerdan hatırla, interrupt dönüşü retie değil mi. Bu global interruptı enable yapıyor. Şunu derseniz katılırım, interruptan çıkmadan önce set edilen flag resetlenmeli. Bunu da zaten CCS (Default yada Global interruptan biri hariç) hepsi için yapıyor. Öyle değil mi?

İnterrupta istenildiği kadar kod yazılabileceğini ben de uygulamalarımdan biliyorum. Hatta bir uygulamada interrupt içerisinden subroutine bile çağırmıştım. Yeterki worst case stack kullanımı sınırını aşmasın.
“Önyargıları yıkmak atomu parçalamaktan zordur” A.Einstein

SpeedyX

Alıntı yapılan: "Petek"Hocam, int geldiğinde interrupta gidiyorsun ya, zaten o arada GIE biti 0 oluyor. Assemblerdan hatırla, interrupt dönüşü retie değil mi. Bu global interruptı enable yapıyor.

Gie otomatik olarak 0 mı oluyor?
Ben onu olmuyor diye biliyorum, mesela şöyle bir program olsun:
#include <16F84.h>
#use delay(clock=3276800,RESTART_WDT)
#fuses NOWDT,XT,NOPUT,NOPROTECT

#include "lcd.c"
int x;

#int_rtcc
void RTCC_ISR() {
   x++;
   if(x==200) x=0;
   }
}

void main() {
   setup_counters(RTCC_INTERNAL,rtcc_div_8);
   enable_interrupts(int_rtcc);
   enable_interrupts(global);
   set_tris_b(0x00);

   lcd_init();
   lcd_gotoxy(1,1);
   Lcd_putc("\fSpeedyX");

   delay_ms(2000);

   while(true)
   {
      lcd_gotoxy(1,2);
      Lcd_putc("x=");
      printf(lcd_putc,"S:%02lu",x);
      delay_cycles(1);
   }
}

bu şekliyle çalışacaktır, birde şu şekilde değiştirelim:
#int_rtcc
void RTCC_ISR() {
   disable_interrupts(global);
   x++;
   delay_ms(5000); // 5 Saniye bekle
   if(x==200) x=0;
   enable_interrupts(global);
   }
}

bana göre bu şekliylede çalışacaktır fakat;
#int_rtcc
void RTCC_ISR() {
   x++;
   delay_ms(5000); // 5 Saniye bekle
   if(x==200) x=0;
   }
}

yine bana göre şu şekliyle düzgün çalışmaz, iç içe interrupt alır.
Eğer ISR içerisinde gie otomatik olarak kapatılıp, çıkışta aktif yapılıyorsa yeni birşey daha öğrenmiş olurum.

kalman

@Arkadaşlar verdiginiz cevaplardan dolayı herkese teşekkürler :lol:

Fakat tabiri caizse eskilerin dediği gibi bir arpa boyu yol alamadık bu konuda :lol:  :lol:

@erkan coff ile denedim önce ISR e gidiliyor fakat sonra ISR terk edilmiyor PİC CPU REGISTER e baktığımda  INTCON Registerin ilk biti
sıfırlanamıyor veya resetlenemiyor   Petek in RBıf=0 öneriside bir şey değiştirmedi tek çare belkide ISR in içinde bunu ASM ile yapmak
ama o haldede ccs in avantajı yok olmazmı ???

C18 sizce tek çözümmü aslında CCS C ide bayağı beyenmiştim neyse
Büyük ustalardanda henüz bir cevap yok   ;)  ;)

Öğrenilmesi kolay denilen bir derleyicinin hatalı olduğu halde tavsiye edilmesi bence doğru değil ve bu açıkca belirtilmesi gerekir

Ufukta C18 gözüküyor 8)  8)

herkese başarılar

saygılarımla