Timer0 interruptı içinde devir sayma ve kronometre problemi

Başlatan eR2, 15 Ocak 2014, 14:13:07

eR2

merhabalar, timer0 interruptı ile devir sayıyorum (timer1 den gelen pulsları ölçerek), bana bir de kronometre gerekiyor.. kesme her 66ms de bir oluşuyor, daha önce timer0 kesmesi ile kullandığım projem var fakat ikisini birden yapmaya çalışıyorum.

timer0 0-256 arası sayarken, 217 de kronometreyi başlatmak için timer0 ın 217 de olduğu bilgisini nasıl alabilirim? aklıam gelen tek yöntem bu, kodlarım aşağıdadır..

alttaki kod timer0 kesmesi ile devir okuduğum bölüm

#BIT T0IF = 0x0B.2

#INT_rtcc
   clock_isr()
   {
      if(T0IF)
      {
        
         sayac=sayac+1;

         if(sayac==15)
         {
            hiz=get_timer1();
            hiz=hiz/2;                     
            y=hiz-(hiz%10);
            
         lcd_gotoxy(1,1);
         printf(lcd_putc,"hiz=%lu P%3.0f D%3.0f",y,P,D);
            sayac=0;
   
         set_timer1(0);
            
          
         }
      }
   }
void main()
{
     
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RTCC);
   set_timer0(0);
   set_timer1(0);
   setup_timer_1(T1_EXTERNAL);
   ext_int_edge( 1,H_TO_L );
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);

}



alttaki kod ise kronometre ve geri sayıcı
#int_timer0
void timer0_kesme()
{

set_timer0(217);
_10ms++;
__10ms--;
if(_10ms==100)
{
_10ms=0;
saniye++;
if(saniye==60)
{
saniye=0;
dakika++;
}
}
if(__10ms==0)
{
__10ms=59;
_saniye--;
if(_saniye<=0)
{
_saniye=59;
_dakika--;
if(_dakika<=0) _dakika=0;

}
}
}

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);

   
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
   set_timer0(217);
   
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
   ext_int_edge(L_TO_H);

}


yldzelektronik

Projeni azıcık daha açıklayıcı ifade eder misin?Pek bişey anlamadım.Üstüne bir de kafamı karıştırdı.???
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

eR2

Alıntı yapılan: yldzelektronik - 15 Ocak 2014, 14:23:56
Projeni azıcık daha açıklayıcı ifade eder misin?Pek bişey anlamadım.Üstüne bir de kafamı karıştırdı.???

halihazırda çalışan bir devir ölçer projem var ve deviri timer0 kesmesi ile hesaplıyorum (timer1 den gelen pulsları 66ms de bir sayarak).. eklemek istediğim bir koronometre ve gerisayıcı devresi, atıyorum; örneğin menuden gerisayıcıyı 5dk ayarlıyoruz ve deviri 5dk boyunca lcd ekranda gösterip 5dk bitince çıkış yapıyor..

Sorunum şu, kronometreyi de timer0 kullanarak yapıyorum, hem devir ölçümünü hem de kronometreyi timer0 içinde nasıl yapabilirim?.. timer0 0-256 arasında(66ms) devir ölçüyor fakat 217-256 arasında da kronometre için kullanıyorum..Kodlarım yukarıda mevcut.. timer0 0 dan başlayıp sayarken 217 ye geldiğinde bu bilgiyi alabilirsem, atıyorum; if(timer0==217) {kronometre hesabı} bu şekilde yaparım sanıyorum.. Son çare timer3 modülü olan 18f4520 kullanmak

serhat1990

Merhabalar eğer doğru anladıysam bu fonksiyon işinize yarayabilir. Eskiden ccs c ile çalışırken bu fonksiyonu kullanmıştım. İyi çalışmalar .

get_timer0(value);


Timer0' ın sayma değerini size döndüren fonksiyon hatırladığım kadarıyla.

eR2

Alıntı yapılan: serhat1990 - 15 Ocak 2014, 16:01:13
Merhabalar eğer doğru anladıysam bu fonksiyon işinize yarayabilir. Eskiden ccs c ile çalışırken bu fonksiyonu kullanmıştım. İyi çalışmalar .

get_timer0(value);


Timer0' ın sayma değerini size döndüren fonksiyon hatırladığım kadarıyla.

çok teşekkür ederim, get_timer1() kullanmama rağmen aklıma gelmedi(biraz yoğunum bu aralar ???), sorunum halloldu sanıyorum..

selimkoc

timer0 217'de kesme oluştursun. Bu kesme altında timer1 on yaparsın.

yldzelektronik

Amaç yalnızca o anki timer değerini almak mı?yoksa başka bir problem mi var?

get_timerx() ile istenen timer değeri alınabilir.

Farklı bir sorun varsa çözüm olur mu bilmiyorum ama timer 2 kullanılabilir.Tabii başka amaçlar için kullanılmıyorsa..Bazı mcularda timer4 de oluyordu.

Birazuğraştırır ama timer 0 çözünürlüğünü dikkatlice ayarlayıp istenen birçok iş için kullanılabilir.

Örneği her 1 ms de bir int oluşturursun ve sayaç kurarsın.İstediğin sayaca göre de  işlemlerini main içinde yaparsın.

Bu arada timer 0 içinde printf vs kullanmamanı öneririm.Uarta veri basarken printf 2 yada 3 karakter veri gönderimini 30 küsür ms de tamamlıyor.Ccs de hem gerçek devrede hem de simülasyonda test ettim.(9600 baud)

Ben meseleyi tam olarak halen anlamadığımdan daha fazla yardımcı olamıyorum.Üzgünüm.

Pcb çiziyorum şuan.Kafam pek yerinde değil galiba... ???
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

eR2

Alıntı yapılan: selimkoc - 15 Ocak 2014, 16:43:00
timer0 217'de kesme oluştursun. Bu kesme altında timer1 on yaparsın.

Hocam dediğinizi denedim, anlamadığım bir nedenden dolayı devir bilgisi değişti..

Alıntı yapılan: yldzelektronik - 15 Ocak 2014, 16:57:08
Amaç yalnızca o anki timer değerini almak mı?yoksa başka bir problem mi var?

get_timerx() ile istenen timer değeri alınabilir.

Farklı bir sorun varsa çözüm olur mu bilmiyorum ama timer 2 kullanılabilir.Tabii başka amaçlar için kullanılmıyorsa..Bazı mcularda timer4 de oluyordu.

Birazuğraştırır ama timer 0 çözünürlüğünü dikkatlice ayarlayıp istenen birçok iş için kullanılabilir.

Örneği her 1 ms de bir int oluşturursun ve sayaç kurarsın.İstediğin sayaca göre de  işlemlerini main içinde yaparsın.

Bu arada timer 0 içinde printf vs kullanmamanı öneririm.Uarta veri basarken printf 2 yada 3 karakter veri gönderimini 30 küsür ms de tamamlıyor.Ccs de hem gerçek devrede hem de simülasyonda test ettim.(9600 baud)

Ben meseleyi tam olarak halen anlamadığımdan daha fazla yardımcı olamıyorum.Üzgünüm.

Pcb çiziyorum şuan.Kafam pek yerinde değil galiba... ???
Yeterince yardımcı oldunuz hocam çok teşekkür ederim.
printf i kesme dışına aldım fakat buseferde devir bilgisini yazdıramadım, nasıl yapabilirim?

sadogan

main nin altında sonsuz döngüyü göremedim .
printf fonsiyonunu nereye aldınız ?

yldzelektronik

Hocam kodları daha açık şekilde paylaşmanızda sakınca yoksa daha rahat yardımcı olunabilir.

Ben bişey diyemiyorum.Nereye aldın,nasıl aldın da devir bilgisini yazdıramıyorsun.

Yazdıramadın ama nasıl?Yani değişken değeri olarak 0 mı,anlamsız değerler mi,lcdde ilgili satır/sütün boş mu?Yani bu şekilde bir şey ben söyleyemiyorum.Bağışla lütfen.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

eR2

Alıntı yapılan: yldzelektronik - 15 Ocak 2014, 23:40:08
Hocam kodları daha açık şekilde paylaşmanızda sakınca yoksa daha rahat yardımcı olunabilir.

Ben bişey diyemiyorum.Nereye aldın,nasıl aldın da devir bilgisini yazdıramıyorsun.

Yazdıramadın ama nasıl?Yani değişken değeri olarak 0 mı,anlamsız değerler mi,lcdde ilgili satır/sütün boş mu?Yani bu şekilde bir şey ben söyleyemiyorum.Bağışla lütfen.
kodları ekledim hocam..

Alıntı yapılan: sadogan - 15 Ocak 2014, 19:50:14
main nin altında sonsuz döngüyü göremedim .
printf fonsiyonunu nereye aldınız ?

hocam kodları aşağıdaki gibi yapınca ekranda bişey göremiyorum..printf interrupt ın içinde olunca ekranda birşeyler görebiliyorum

#include <16f877a.h>
   #fuses XT,NOWDT,NOPROTECT
   #use delay(clock=4000000)
   #include <stdlib.h>
   #include<lcd.c>
   #BIT T0IF = 0x0B.2
   
   int sayac;
   long hiz;
   int16 value;
   
   #INT_rtcc
   clock_isr()
   {
      if(T0IF)
      {
         
         sayac=sayac+1;

         if(sayac==15)
         {
            hiz=get_timer1();
            hiz=hiz*1.4;

            sayac=0;
            
            set_timer1(0);
         }
      }
   }
   
   void main()
   {

      hiz=0;
      sayac=0;
      
      enable_interrupts(GLOBAL);
      enable_interrupts(INT_RTCC);
      set_timer0(0);
      setup_timer_0(RTCC_DIV_256);
      set_timer1(0);
      setup_timer_1(T1_EXTERNAL);
      ext_int_edge( 1,H_TO_L );
            
      lcd_init();

      setup_timer_2(T2_DIV_BY_4, 1023, 1);
      setup_ccp1(CCP_PWM);
      setup_port_a(ALL_ANALOG);
      setup_adc(adc_clock_internal);
      set_adc_channel(0);

      while(true)
      {
         value=read_adc();
         value=value*4;
         set_pwm1_duty(value);
         printf(lcd_putc,"\f  rpm  :  %LU d/d\n duty=%lu ",hiz,value);
    
      }
   }

yldzelektronik

@eR2

Ben yazdığınız programdan hiçbir şey anlamadım.

Rtcc int kullanmışsınız.Isr içinde ayrıca flag sorgulamışsınız.Zaten o isr ye girmesi için sorguladığınız flagın set olması gerekli.

Diğer bir konu hiz değişkenini işaretli long tanımlamışsınız.Yani bu sayı ile çıkabileceğiniz max değer 32767 (65535/2) olabilir.Ancak tam sayı olabilir.

Yani hiz = hiz*1.4 kasıtlı yapmadıysanız size veri kaybı yaşatır.

Diğer bir sorun timer 2.Timer 2 max 255 değerini alabiliyor diye biliyorum.

Ayrıca bir soru sormak istiyorum.

Timer 1 pinlerinden devir mi ölçmek istiyorsunuz?

Eğer öyle ise neden external interrupt egde select yapıyorsunuz?

Belirli bir sürede devir ölçmek için ra4 pinidaha iyi bir seçim olur diye düşünüyorum.İlla ki timer 1 ile yapmanız gerekiyorsa timer 1 int kullanmayı deneyin.Her int içine girdiğinizde 16bit timer değerini alır hesabınızı ona göre yaparsınız.Hız çok yüksek değilse mcu frekansınızı da min da tutarsınız.

Bilmiyorum sadece ben mi anlamadım ama daha açıklayıcı olursanız, tam olarak ne yapmaya çalıştığınızı ifade ederseniz daha net yardım edebileceğimi düşünüyorum..

Bağışlayın lütfen.Halen tam olarak ne yapmaya çalıştığınızı kodlarınızdan dolayı kavrayamadım.
Kişinin başına gelen hayır Allah'tandır. Kişinin başına gelen şer nefsindendir. Nefislerimizle kendimize zulüm ediyoruz.

eR2

Alıntı yapılan: yldzelektronik - 20 Ocak 2014, 11:06:43
@eR2

Ben yazdığınız programdan hiçbir şey anlamadım.

Rtcc int kullanmışsınız.Isr içinde ayrıca flag sorgulamışsınız.Zaten o isr ye girmesi için sorguladığınız flagın set olması gerekli.

Diğer bir konu hiz değişkenini işaretli long tanımlamışsınız.Yani bu sayı ile çıkabileceğiniz max değer 32767 (65535/2) olabilir.Ancak tam sayı olabilir.

Yani hiz = hiz*1.4 kasıtlı yapmadıysanız size veri kaybı yaşatır.

Diğer bir sorun timer 2.Timer 2 max 255 değerini alabiliyor diye biliyorum.

Ayrıca bir soru sormak istiyorum.

Timer 1 pinlerinden devir mi ölçmek istiyorsunuz?

Eğer öyle ise neden external interrupt egde select yapıyorsunuz?

Belirli bir sürede devir ölçmek için ra4 pinidaha iyi bir seçim olur diye düşünüyorum.İlla ki timer 1 ile yapmanız gerekiyorsa timer 1 int kullanmayı deneyin.Her int içine girdiğinizde 16bit timer değerini alır hesabınızı ona göre yaparsınız.Hız çok yüksek değilse mcu frekansınızı da min da tutarsınız.

Bilmiyorum sadece ben mi anlamadım ama daha açıklayıcı olursanız, tam olarak ne yapmaya çalıştığınızı ifade ederseniz daha net yardım edebileceğimi düşünüyorum..

Bağışlayın lütfen.Halen tam olarak ne yapmaya çalıştığınızı kodlarınızdan dolayı kavrayamadım.

Hocam flag sorgulama kısmını kaldırdım, dediğiniz gibi bir gereği yoktu.. bana max değer 3000 4000 tam sayı olarak yetiyor.

timer2 şu an 1,65,1 olarak ayarlı..

ra4 pininden deviri nasıl sorgulayabilirim? yada timer1 int ile?..Açıkcası bu kodları ccs forumlarından referans alarak yapmıştım, amacım devir ölçmek 0-3000rpm aralığında..

altta interrupt fonsiyonumun son hali var hocam sıkıntım hala devir bilgisini interrupt dışında yazdıramıyorum..

#INT_rtcc
   clock_isr()
   {
     
         sayac=sayac+1;

         if(sayac==7) 
         {
            hiz=get_timer1();
           
            y=hiz-(hiz%10);


         lcd_gotoxy(1,1);
         printf(lcd_putc,"hiz=%lu d/d",y);
            sayac=0;
            
         set_timer1(0);
            
         }
        }