PIC interrupt

Başlatan mr.engineer, 25 Temmuz 2020, 11:31:44

mr.engineer

Merhaba aşağıda bir timer kesme fonksiyonu paylaşıyorum.
Her 1 ms de kesme oluşup bu fonksiyona giriyor ve ADC'den bir değer okuyorum.
Fosc frekkansı 16 MHz.
ADC clock frekansı 8 MHz olarak ayarlı.

Sorun şu ki; ISR fonksiyonu sürekli çalışıyor ve main fonksiyonuna dönmüyor. ISR fonksiyonunun başında ve sonunda bir pini toggle yaparak ISR fonksiyonunun çalışma süresini ölçtüm yaklaşık 1.2 ms sürüyor, zaten 1 ms de bir kesme olduğundan bu fonksiyon tüm süreyi yiyor ve bu fonksiyondan çıkamıyorum.

Daha sonra bu sürenin nerede harcandığına bakmak için satır satır süreleri ölçtüm ve şu satırın tek başına neredeyse 1 ms süre harcadığını gördüm.

adcval=( ( adcval * (3.3 * 1000.0) ) / 1024 );


 
void __interrupt () my_isr_routine (void)  /* Timer0 interrupt every 1 ms*/
{  
    static int count=0;
    static int second_wait=0;
    unsigned short adcval_H=0;
    unsigned short adcval_L=0;

    if(TMR0IF==1)
    {
        TMR0 = 131;     /*Load the timer Value*/
        TMR0IF=0;       // Clear timer interrupt flag
       ADCON0bits.GO_nDONE=1; // Start ADC
       
       while(ADCON0bits.GO_nDONE)
       {
           ;
       }
       if(ADCON0bits.GO_nDONE == 0)
       {
           adcval_H=ADRESH<<8;
           adcval_L=ADRESL;
           adcval=adcval_H | adcval_L;
           adcval=( ( adcval * (3.3 * 1000.0) ) / 1024 );
       }
    }
}


Daha sonra bu satırı başka bir fonksiyona aldım şu şekilde:

float readVoltage()
{
   return ( ( adcval * (3.3 * 1000.0) ) / 1024 );
}

Bunu yapınca sorun çözüldü main fonksiyonum çalışmaya başladı.
Bunun sebebi nedir yani ilk durumda bu satır neden bu kadar çok zaman harcıyor olabilir?

NOT: TÜM ÖLÇÜMLER PROTEUS ÜZERİNDEN YAPILDI.

sadogan

Merhaba,
(3.3 * 1000.0) ) / 1024 ) bu işlem in sonucu sabit bir sayı deyilmi.
(3.3 * 1000.0) ) / 1024 ) = 3.22, 3.22 ile çarpmak daha hızlı olmazmı neden her seferde
fazladan işlem yapıyorsunuz.

     while(ADCON0bits.GO_nDONE)
       {
           ;
       }
Burda adc çevrim işlemi bitene kadar gereksiz yere bekliyorsunuz.
Adc  interrupt kullana bilirisiniz.

mr.engineer

#2
Alıntı yapılan: sadogan - 25 Temmuz 2020, 12:27:21while(ADCON0bits.GO_nDONE)
       {
           ;
       }
Burda adc çevrim işlemi bitene kadar gereksiz yere bekliyorsunuz.
Adc  interrupt kullana bilirisiniz.


Buradaki bekleme süresi oldukça kısa, interrupt da kullanılabilir fakat sorunun bu değil gibi görünüyor. Yukarıda belirttiğim satırdaki işlem zaman alıyor, tabi reel devrede değil Proteus sonucu böyle.

Alıntı yapılan: sadogan - 25 Temmuz 2020, 12:27:21(3.3 * 1000.0) ) / 1024 ) bu işlem in sonucu sabit bir sayı deyilmi.
(3.3 * 1000.0) ) / 1024 ) = 3.22, 3.22 ile çarpmak daha hızlı olmazmı neden her seferde
fazladan işlem yapıyorsunuz.

Dediğiniz şekilde de düzelttim ama yine de uzun zaman alıyor.
Yani aşağıdaki işlem neredeyse 1 ms sürüyor.

adcval=( ( adcval *3,22));

Yani bu işlemin 3-5 clock cycle'da bitmesi gerekiyor, neden bu kadar uzun zaman alıyor anlayamadım.

Tagli

Kayar noktalı (floating point) sayılarla işlem yapıyorsun, 3-5 cycle'da bitmesi mümkün değil. 100-200 cycle falan sürebilir. Yine de 1 ms bana uzun geldi. İşlemcinin hızı da önemli tabi.

Bir de ben olsam Proteus'a pek güvenmezdim.
Gökçe Tağlıoğlu

RaMu

Alıntı yapılan: mr.engineer - 25 Temmuz 2020, 13:42:56...
adcval=( ( adcval *3,22));

Yani bu işlemin 3-5 clock cycle'da bitmesi gerekiyor, neden bu kadar uzun zaman alıyor anlayamadım.
3-5 clock biraz zor fpu kesirli çarpma modülü olan mcu lazım ona.

Yinede 1 ms sürmez büyük ihtimalle.

1 ms olduğunu nasıl ölçüyorsun?
Proteus debug modda kodu adım adım çalıştırıp
sağ altta gösterdiği zamanı takip ederek ölçebilirsin.
Proteusun osiloskobunu kullanabilirsin.

...
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

mr.engineer

Alıntı yapılan: RaMu - 25 Temmuz 2020, 14:09:573-5 clock biraz zor fpu kesirli çarpma modülü olan mcu lazım ona.

Yinede 1 ms sürmez büyük ihtimalle.

1 ms olduğunu nasıl ölçüyorsun?
Proteus debug modda kodu adım adım çalıştırıp
sağ altta gösterdiği zamanı takip ederek ölçebilirsin.
Proteusun osiloskobunu kullanabilirsin.

...

RD0=1;
adcval=( ( adcval *3,22));
RD0=0;

Koda bunu yazdıktan sonra, RD0 pinini osilokopa bağlıyorum. Yaklaşık 1ms sürüyor.

RaMu

Alıntı yapılan: mr.engineer - 25 Temmuz 2020, 11:31:44...
Fosc frekkansı 16 MHz.
...
Pic32 kullanmıyorsan, bu frekansta çalışırken 1us de 4 komut işliyor mcu.
1ms geçmesi için 4000 komut işlemesi lazım,
o çarpma işlemini 4000 komutta yapıyor olma ihtimali çok düşük.
Kodun ilgili fonksiyonun assembler karşılığına bak.
Birde osiloskop görüntüsüdd ekle
bence bir şeyi gözden kaçırıyorsun.

Yinede @Tagli ye katılıyorum
proteusa fazla güvenme.
Bu kadar uğraşacağına gerçekte denersin zaten.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

sadogan

Hangi pic bu ?
Kullandığını derleyici destekliyorsa floating point yerine fixsed point kullanın.