Timer0 Kesme hesabı sorunu

Katılım
26 Ocak 2010
Mesajlar
7
Puanları
1
Yaş
29
Merhabalar,
Rc servo motor kullanarak bir robot kolu tasarladım.18f4550 kullanmaktayım.Serdar ÇİÇEK'in paylaşmış olduğu timer0 kesmeli servo motor kontrol programı kullanmaktayım.Gayet güzel çalışıyor.Fakat önceden 20MHZ kristal kullanıyordum.Usb kontrolü kullandığım için PLL kullanarak Kristalimi 48MHZ olarak kullanıyorum.

Bu nedenle 20 MHZ deki set_timer0(113) değeri olmuyor.set_timer değerini hesaplama konusunda yardımcı olursanız sevinirim.


Bu program 20MHZ kullanınca sorunsuz çalışıyor.Fakat PLL ile 48 MHZ kullanınca bütün hesaplar karışıyor :/
Kod:
#include <18F4550.h>
#device ADC=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOBROWNOUT
#use delay(clock=48000000)

#use fast_io(b)
#use fast_io(d)


int pwm=0,duty_0=0,duty_1=0,duty_2=0,duty_3=0,duty_4,duty_5=0,duty_6=0;
int16 zaman=0;

#int_timer0  // Timer0 taşma kesmesi
void kesme ()
{
   set_timer0(113);  // TMR0 kaydedicisine 113 değeri yükleniyor
   if (pwm==0)       // Eğer PWM değişkeni 0 ise
   {
      output_high(pin_b0); // RB0 çıkışı lojik-1
      output_high(pin_b1); // RB1 çıkışı lojik-1
      output_high(pin_b2); // RB2 çıkışı lojik-1
      output_high(pin_b3); // RB3 çıkışı lojik-1
      output_high(pin_b4); // RB4 çıkışı lojik-1
      output_high(pin_b5); // RB5 çıkışı lojik-1
      output_high(pin_b6); // RB6 çıkışı lojik-1
   }

   if (pwm>=duty_0) output_low(pin_b0);
   if (pwm>=duty_1) output_low(pin_b1);
   if (pwm>=duty_2) output_low(pin_b2);
   if (pwm>=duty_3) output_low(pin_b3);
   if (pwm>=duty_4) output_low(pin_b4);
   if (pwm>=duty_5) output_low(pin_b5);
   if (pwm>=duty_6) output_low(pin_b6);

   zaman++; 

   // Servo motor dönüş adımları arası bekleme süresi için
   if (zaman>17350) // 17350x114,4µsn=1.984.840µsn, yaklaşık 2msn
   {
      zaman=0; 
   }

   pwm++;
   if (pwm>=173) 
      pwm=0; 
}


void main(void)
{     
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_4);
   set_timer0(113); 
   enable_interrupts(int_timer0); 
   enable_interrupts(global); 
   output_b(0x00); 

while(1) {
duty_0=9;
}
   }
 
Ben asmciyim diğer dillerden anlamam.. Ama sistemin mantığını düşünürsek tahminime göre;
256-[((256-113) /20)*48] = -87,2

gibi bi değer vermen gerekir eski zamanlamayı tutturabilmek için.. Ancak bu atama 8 bitlik registere yapılır ve negatif değer alamaz.. TMR0 ın bölme oranını 2 kat arttırmalısın.. Sanırım alttaki gibi yapacaksın..

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8);

RTCC_DIV_8; yukarıdaki bu değer bölme oranını arttırıyor, tahminim böyle yapman gerekir..


Tmr0 ın bölme oranını arttırdıktan sonra;

256-[((256-113) /20)*48]/2 = 84,4

bu şekilde timer0 değerine atamayı hesaplayacaksın..

Yani yaklaşık 84 değerini atayabilirsin.. Eğer biraz daha hassas olsun istersen kesmedeki değer atamasından önce nop komutu ekleyebilirsin.. Bölme oranı 8 ise en fazla 8 komut ekleyerek hassaslığı arttırabilirsin..

Bu arada 113 atamasının sebebi, tmr0 kesmesi 255ten 0a geçerken kesme oluşturur.. Haliyle 256-113=143 sayımlık süre geçirir.. Tahminim burada 143*4=572 saykıl..

Ayrıca ben asmci olduğum halde stopwatch ile bunları defalarca deneyerek yaparım.. Hesap hatası var mı yok mu hata ayıklayabilirseniz iyi olur..
 
Son düzenleme:
Merhaba hocam,
öncelikle konuya cevap yazdığınız için teşekkür ederim.Hesabın mantığını anladım fakat çalıştıramadım.Sorun değerlerle alakalı değil.

Ben 20MHZ lik 16f877 de kesme programını denedim çalışıyor.Fakat usb kullandığım için 18f4550 kullanıyorum.Aynı programı 18f4550 yi usb siz şekilde 20MHZ de deniyorum.Normal program çalışıyor fakat timer0 kesmesi çalışmıyor :/

Sizce neden kaynaklı olabilir ?
 
Son düzenleme:
Valla programlama dilinde bilinmesi gereken bi püf nokta var mı bilemem.. Ama yine tahminime göre;
tmr0 ayarlarında
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8);
komutuna sayacın 8 bit olması için bi komut eklenmeli sanırım.. Tahminen sayısal değeri h'40' olmalı..
Veya 113 değeri yerine 65536-(256-113) değeri atanmalı.. Kesme oluyor, fakat çok geç oluyorsa sebebi bu olabilir..

Aklıma başka bişey gelmiyor..
 
Valla programlama dilinde bilinmesi gereken bi püf nokta var mı bilemem.. Ama yine tahminime göre;
tmr0 ayarlarında
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8);
komutuna sayacın 8 bit olması için bi komut eklenmeli sanırım.. Tahminen sayısal değeri h'40' olmalı..
Veya 113 değeri yerine 65536-(256-113) değeri atanmalı.. Kesme oluyor, fakat çok geç oluyorsa sebebi bu olabilir..

Aklıma başka bişey gelmiyor..

Hocam 10 dakka önce olayı çözdüm.Oturup timer0 la bol bol örnek yaptım.Bunca zaman boşuna korkmuşum.:)Dediğiniz gibi setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8|RTCC_8_bit); şeklinde bitini de belirtmek gerekiyormuş.Bu arada verdiğiniz değer sorunsuz çalışıyor.

Teşekkür ederim.
 
Aletler bize hizmet için varlar , yormayın kendinizi.
Pic için gereken hesapları kolayca yapabilen araçlar var basit küçük etkili :

https://www.kontrolkalemi.com/forum/attachments/pic-calc-rar.28536/

--------

@GüvTek yeter artık asm ile tırmaladığın.
Gidebileceğin yol bir arpa boyu .
Kendini geliştirmek , ledyaksöndür den öte projelerle uğraşmak istiyorsan bir an önce C öğrenmeye bak.
Asm ile picin içini yapısını temelini öğrendin yeter çok bile.
Pic ya da diğerleri , 32 bitlere işletim sistemi kurup image processing takılıyor millet.
Tabii bunları asm ile yapmıyorlar...
 

Ekli dosyalar

  • Pic Calc.rar
    108.9 KB · Görüntüleme: 43
Hocam valla ledyak söndürden çok daha öteye gittiğime inanıyorum.. Aslında diğer diller beni kısıtlıyor, asm de tek kısıtlama donanım.. Kütüphane sistemi yaygınlaşmaması bazı şeylerde zorluyor.. Kafama eserse C dilini de öğrenecem ama,, yine de atalarımız en kısa yol bildiğin yoldur demişse haklılık payı vardır illaki.. :)

Zaten kpss atamalarına az kaldı,, belli olmaz ama atanırsam bu işleri bırakırım heralde.. :)
 
Pic'in Osilatör Frekansını değiştirdiğin zaman doğal olarak timerlerin değerlerinide değiştirmen gerekir.
Kullandığın bütün timer donanımları osilatör frekansı değişiminden dolayı etkilenecektir.

CCS nin picwizard'ından yararlanabilirsin.
 

Forum istatistikleri

Konular
128,130
Mesajlar
915,289
Kullanıcılar
449,847
Son üye
AhmetK06

Yeni konular

Geri
Üst