Kontrol amaçlı Interrupt

Başlatan yldzelektronik, 28 Eylül 2013, 16:35:27

yldzelektronik

Selamlar.

Kullandığım mcu pic16f1825. Derleyici Ccs. Yaşadığım sıkıntı interrupt içinden çıkarken istediğim adrese gidemiyorum. Şöyle ki;

Ana program içinde dönen toplamda 4 fonksiyon var.Bu fonksiyonların toplamda harcadıkları süre belli ve sabit.

Cihaz çalışma ortamı itibari ile elektriksel gürültünü yoğun olduğu bir ortam değil.Genel itibariyle.

Ancak hem çok uzak noktalarda (müdahale anlamında) hem de sıkıntı çıkması ihtimaline karşı bir kaç tedbir almak istedim.

Bu amaçla interruptları fonksiyonların işlem süresinden bir kaç mikro saniye daha fazlasına kurup yerine göre her fonksiyon için gereken timer int bayrağını açıyorum.Fonksiyon normal sürede işini bitirdiğinde kesme bayrağını kapatıyor.Eğer olur da fonksiyon bir şekilde işini yapamaz ve program bir şekilde çakılırsa timer int gelecek ve fonksiyondan çıkıp isr (interrupt servis rutine) ye gidecek. Ancak bu noktadan sonra takıldım.Mcu isrden çıkarken tekrar kaldığı yere geri dönecek. Ki kesme mantığı kabul.Ancak benim istediğim böyle bir durumda kesmeye giderse ana program içine dönsün.

Bunu ccs nin bazı fonksiyonlarını kullanarak yapmak istedim ancak başarılı olamadım. Sanırım kesmeden normal çıkmadığı için.Ki bu da kesmeden çıkarken status, pc (program counter) vs gibi registerleri geri yükleyememesinden kaynaklanıyor.Emin değilim.

Watch dog timer kullanmak istemiyorum.Çünkü wdt kullandığımda mcu resetleniyor ve bu benim pek işime gelmiyor.Wdt yi son çare olarak düşünüyorum.2 yada 3 saniyeye kurmayı düşünüyorum.Eğer 3 saniye çakılı kalırsa wdt resetlesin istiyorum.

Yeterince açık ifade edebildim mi bilmiyorum.

Örneğin;

#int_timerx
void timerx_isr(){
               goto_address(0x1634);        //bir de label_address(label) fonksiyonu ana program içinde herhangi bir yerde label kullanınca onun adresini döndürüyor.ancak bunu kullandığıda;

//goto_address(label_address(main_pogram)); hata mesajı alıyorum.tanımlanmamış label kullanımı tarzı bir error.
       
}
void main(void){
   .
   .
   .
         while(TRUE){
                  .//dönmek istediğim satır.
                  .
                  .
                  .
                  degisken = calculate(x,y);
       }
}
unsigned int16 Calculate(float min_value,float max_value){
  set_timerx(0);
   enable_int(timerx);   
/*
   min_value: min basınç değeri
   max_value: max basınç değeri
   */
   unsigned int16 calc = 0;
   /*
   .
   .        //Burada yazılmış kodlar olacak.
   .
   */
   Task_Status = Succesfull;
   disable_int(timerx);
   return calc;
}


Şeklinde bir fonksiyonum olsun.Fonksiyonun normalde işlenme süresi de 1,25 mili saniye olsun.

fonksiyona girişte timer 0lanacak ve int kurulacak.Fonksiyonun çıkışında ise int kapatılacak. Eğer son satıra gelemezse program akışı bir şekilde, o durumda intterrupt gerçekleşecek ve oradan çıkılmış olacak.

Ancak isr den dönerken nasıl ana programa dönebilirim?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

kantirici

Hocam bence siz wacthdog timer kullanın.

yldzelektronik

Alıntı yapılan: kantirici - 28 Eylül 2013, 16:43:55
Hocam bence siz wacthdog timer kullanın.

Wdt çok can sıkıcı oluyor.Dedim ya onu en son çare olarak kullanmak istiyorum.Resetten sonra yüklemesi gereken sürüyle değişken var.Pek işime gelmiyor.Bir çözümü olmalı diye düşünüyorum.Program counter a müdahele etmeden olmayacak sanırım???
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

yldzelektronik

Bu sorun gerçekten bu kadar zor bir sorun mu?Neden kimse bir öneride bulunmaya tenezzül etmemiş?Yada gerek duymamış.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

z

Problemi bir kez daha  daha iyi anlasilir sekilde yazsan belki yorum yapilir.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

yldzelektronik

Alıntı yapılan: z - 29 Eylül 2013, 14:19:41
Problemi bir kez daha  daha iyi anlasilir sekilde yazsan belki yorum yapilir.


I2c busa bağlı sensör var.Sensör arada kafasına göre cevap vermeyi kesebiliyor.Yani adresini yazıyorum cevap vermiyor.Adrese cevap veriyor ölçümlerini göndermiyor.O herhangi bir cevap vermeyince hard i2c kullandığımdan program oturup bekliyor.Yani çakılıyor.
[while(SSP1STAT.BF); tarzı bekleme noktaları var.]

Ben de diyorum ki böyle durumlar oluşmasın diye bir timer kurayım, o timer o satırdan çıkarsın.Şöyle;

5 adet fonksiyonum ana döngü içinde çalışsın.
void main(){
  ...
  ....
  ......
  while(){
   fonk1();
   fonk2();
   fonk3();
   fonk4();
   fonk5();
 }
}


Bu fonksiyonların biri i2c sensörden ölçüm alsın,biri gelen ham veriyi hesaplasın (float değişken çoğunlukta), hesaplanan float değerden 16bit değer çıkaran ayrı hesap fonksiyonum olsun,hesaplanan float değeri/değerleri uarta basan fonksiyonum olsun,bir de başka bir çipe 3 pin ile 16bit değeri yazan fonksiyonum olsun.

Genelde i2c tarafında yaşadığım sorun,sensörün cevap vermeyi kesmesiyle başlıyor.Sensör cevap vermediğinde fonksiyonda tanımlandığı üzere while(ACKSTAT); gibi, program çakılıp kalıyor.Bir hata oluşsa dahi program bunu raporlayamıyor. Böyle olunca da log etme işi sıkıntıya düşüyor.

Şimdi ben diyorum ki program herhangi bir fonksiyonu çağırmadan önce timer int açayım, tabii timerları en başta kurayım, timer beklesin.

Örneğin fonk1 normal şartlarda işini 10us de bitirebiliyor olsun.Benim en uzun fonksiyonum da 200us de işini bitirebilsin.Ben timeri en uzun süren fonksiyona göre kurayım,fonksiyon girişinde açayım çıkarken kapatayım.

void main(){
  ...
  ....
  ......
  while(){
  enable_isr_timerx();
   fonk1();
   disable_isr_timerx();
   fonk2();
   fonk3();
   fonk4();
   fonk5();
 }
}


gibi.Timer isr içinde de mcuyu resetleyeyim. Rtos gibi sanki.Bundan daha pratik nasıl çözümler olabilir?Yada bu sizce tutar mı?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

mistek

#6
I2C fonksiyonlarını siz mi yazdınız ?
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

yldzelektronik

Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

mistek

Mesela programın takıldığı yerleri net olarak biliyorsanız onlara müdahale edebilirsiniz.

while(ACKSTAT)
{
  bekleme++;

  if(bekleme süresi taştı)
     break yada goto
}
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

yldzelektronik

Alıntı yapılan: mistek - 12 Ekim 2013, 12:31:50
Mesela programın takıldığı yerleri net olarak biliyorsanız onlara müdahale edebilirsiniz.

while(ACKSTAT)
{
  bekleme++;

  if(bekleme süresi taştı)
     break yada goto
}


Olabilir aslında.Peki diğer yerlerde takılması durumunda ne yapılabilir?

Örneği rx int içinde gelen karakterler ;

€ø€†˜žæşæx<00>€ø†˜æşæžàşşàøş€şş€øx<00>fşæx<0

şeklinde olduğunda rx isr içinde kalıyor.Nerede ne şekilde takıldığını da anlayamıyorum. İki satır daha işlese program rx isr içinde wdt kurulu ama program ilerlemiyor.Bu tip bir durumda öneri var mı?
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

Klein

genel amaçlı her yerde kullanabileceğin bir timeout kontrolü. her yerden çağıabilirsin.
CCS'e uyarlama işini sen yap.

char timeout(int count) {
static int x, pc =0;
char res =0;

   if(count == 0){
       pc=0;
       return(0); 
    }
   switch(pc){
      case 0:
          x = count;  pc++;  res =1;
          break;
      case 1: 
          if(--x == 0) { pc=0; res=0;}
          break;    
   }
   return(res);
}

// çağırma
while(ACKSTAT && timeout(1000));
timeout(0);



yldzelektronik

Alıntı yapılan: Klein - 12 Ekim 2013, 20:22:30
genel amaçlı her yerde kullanabileceğin bir timeout kontrolü. her yerden çağıabilirsin.
CCS'e uyarlama işini sen yap.

char timeout(int count) {
static int x, pc =0;
char res =0;

   if(count == 0){
       pc=0;
       return(0); 
    }
   switch(pc){
      case 0:
          x = count;  pc++;  res =1;
          break;
      case 1: 
          if(--x == 0) { pc=0; res=0;}
          break;    
   }
   return(res);
}

// çağırma
while(ACKSTAT && timeout(1000));
timeout(0);




Teşekkürler.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.