CCS PCWHD Derleyicide Timer Interrupt Sorunu

Written by bbuyukguzel. Posted in Elektronik, Genel

DSPIC30F4011 ve CCS PCWHD derleyicisini kullanarak gerçekleştireceğim bir projede TIMER1 kesmesi(interrupt) ile  belirli bir periyotta ADC değerlerini okumam gerekti. Son derece basit bir zamanlayıcı uygulaması olan bu iş için aşağıdaki PIC lerle uğraşanların çok aşina oldukları basit kodu yazdım.

TIMER1 setup:

setup_timer1(TMR_INTERNAL | TMR_DIV_BY_64);  // Timer1 ayarları yapılıyor
set_timer1(0x001);   // TMR1 değeri belirleniyor
enable_interrupts(INT_timer1);  // int_timer1 kesmesini aktif yapar
enable_interrupts(INTR_GLOBAL);     // Aktif edilen kesmelere izin ver

TIMER1 kesme servisi:

#int_timer1  // Timer1 kesmesi

void  timer1_kesme ()
 {
int i;
set_tris_D(0x00);
   i=i+1;
   if (i==5)
     output_high(pin_D0);
   if (i==10)
   {
      	output_low(pin_D0);
     	 i=0;
   }
   set_adc_channel(0);
   current1=read_adc();
   set_adc_channel(1);
   voltage1=read_adc();

if (duty<=0x3e0)
duty=0x015e; //d=%35
set_motor_pwm_duty(1,1,(duty));
set_timer1(0x0001); // TMR1 değeri yükleniyor 

}

Programı derleyip DSPIC’e yükledikten sonra kesme periyoduna kontrol etmek amacıyla D0 bacağına osiloskop ile baktığımda D0’ın sabit olduğunu yani kesme işleminin gerçekleşmediğini gördüm.

Problemi analiz için programın assembler listesini incelediğim zaman kesme servisinden çıkarken derleyici tarafından reset edilmesi gereken TIMER1 kesme bitinin (0×0084 bit3) reset edilmediğini anladım.

.................... if (duty<=0x3e0)
0142:  MOV     806,W4
0144:  MOV     #3E0,W3
0146:  CP      W3,W4
0148:  BRA     LT,14E
....................
.................... duty=0x015e;//d=%35
014A:  MOV     #15E,W4
014C:  MOV     W4,806
....................
.................... set_motor_pwm_duty(1,1,(duty));
014E:  PUSH    806
0150:  POP     1D6
.................... set_timer1(0x0001);//TMR1 değeri belirleniyor
0152:  MOV     #1,W4
0154:  MOV     W4,100
....................
....................
.................... }

Aslında derleyici tarafından reset edilmesi gereken bu biti reset etmek için kesme servisinin sonuna clear_interrupt(int_timer1) komutunu ekledim.

if (duty<=0x3e0)
duty=0x015e;//d=%35
set_motor_pwm_duty(1,1,(duty));
set_timer1(0x0001);//TMR1 değeri yükleniyor 

clear_interrupt(int_timer1);

Yeniden derleyip assembler listesini incelediğim zaman ilgili bitin reset edildiğini doğruladım.

.................... set_motor_pwm_duty(1,1,(duty));
014E:  PUSH    806
0150:  POP     1D6
.................... set_timer1(0x0001);//TMR1 değeri belirleniyor
0152:  MOV     #1,W4
0154:  MOV     W4,100
.................... clear_interrupt(int_timer1);
0156:  BCLR.B  84.3
....................
.................... }

Programı DSPIC’e atıp çalıştırdığımda zamanlamanın hesapladığım gibi gerçekleştiğini gördüm.

Tags: , , , , ,

Trackback from your site.

  • Derman

    Çok sağol bend bu sorunu bakıyordum.
    Teşekürler.