Timer interrupt problem

Elektronikrelaterade (på komponentnivå) frågor och funderingar.
FS
Inlägg: 245
Blev medlem: 14 januari 2005, 23:35:45

Timer interrupt problem

Inlägg av FS »

Med denna kod var tanken att få ett interrupt varje 100us. Dock så ger den interrupt om 500us. Värdet som sätts i set_timer0() spelar inte heller någon roll för interrupt tiden, så något är inte riktigt som det borde...

Kör med 4MHz klocka.

Några ideer?

Kod: Markera allt

#include <16F876A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay(clock=4000000)

static int on_off;

#zero_ram

#int_timer0                               // This function is called every
timer0_isr(){                                  // time timer0 overflows 255 -> 0
   if(on_off == 0){
      output_high(PIN_B2);
      on_off = 1;
      }
   else{
      output_low(PIN_B2);
      on_off = 0;
      }
}


main(){
   set_tris_b(0x00);                      // B all outputs
   port_b_pullups(TRUE);

   setup_timer_0(RTCC_INTERNAL);
   set_timer0(220);
	enable_interrupts(INT_TIMER0);
	enable_interrupts(GLOBAL);

   do{
      }while(TRUE);
}
Senast redigerad av FS 22 januari 2005, 22:35:12, redigerad totalt 2 gånger.
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Nu vet jag inte alls vad dessa C-funktioner du anropar gör, men om jag gissar lite så tycker jag det ser ut som du bara laddar in värdet 220 en gång i timern. Så första timer-interruptet borde komma efter 35 cykler och resten med 255 cycklers mellanrum.

255 cykler med 4MHz klocka är 255us, så det stämmer inte riktigt heller.

Testa att ha set_timer0(155) i clock()

Du måste alltså ladda in ett värde i timer0 efter varje interrupt om du vill ha en annan period än 255 på timern. Om nu inte kompilatorn gör det åt dig eller så förstås...
FS
Inlägg: 245
Blev medlem: 14 januari 2005, 23:35:45

Inlägg av FS »

Egentligrn skulle det ha stått set_timer0(156) i min kod. Har provat att sätta in detta i clock() också men fortfarande får jag interrupt efter 500us.

Problemet verkar vara att vad man än sätter in i timer0() får man interrupt efter 500us...


edit: Provade med att sätta in set_timer0(12) i både clock() och main() ändå får jag interrupt efter 500us
FS
Inlägg: 245
Blev medlem: 14 januari 2005, 23:35:45

Inlägg av FS »

Med denna kod får jag nu interrupter efter 100us. Men det är efter att jag har testat mig fram till vilket värde man ska ha i set_timer0(). Med 192 så blev det perfekt. Men det borde ju bli 156 om man räknar på det:

256 - (0.0001/(4/4000000)) = 156

Varför stämmer det inte?

Kod: Markera allt

#include <16F876A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay(clock=4000000)

static int on_off;

#zero_ram

#int_timer0                                    // This function is called every
timer0_isr(){                                  // time timer0 overflows 255 -> 0
   set_timer0(192);
   if(on_off == 0){
      output_high(PIN_B2);
      on_off = 1;
      }
   else{
      output_low(PIN_B2);
      on_off = 0;
      }
}


main(){
	set_tris_b(0x00);                      // B all outputs
	port_b_pullups(TRUE);
   
	set_timer0(192);
	setup_timer_0(RTCC_DIV_1|RTCC_INTERNAL);
	enable_interrupts(INT_TIMER0);
	enable_interrupts(GLOBAL);
   
   do{
      }while(TRUE);
}
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Kanske helt enkelt för att nästa interrupt kommer X cykler efter du laddat värdet i timer-registert, *inte* X cyckler efter det förra interruptet.

Har du titta på assembler-koden som din kompilator genererar? Förmodligen har den så mycket overhead att det tar ~36 cykler från att interruptet kommer tills värdet (192) skrivs in i timer-registret.

Klart, även om man skriver i assembler så tar det några cykler som man får kompensera för, timern fortsätter ju att ticka på 0,1,2,3... osv Bäst är helt enkelt att *addera* det värdet man vill lägga in istället.

Alltså har man ADDWF TMR0 istället för MOVWF TMR0 i sin kod!

Det finns inte någon add_timer0() funktion eller så?
Användarvisningsbild
EagleSpirit
Inlägg: 1288
Blev medlem: 27 maj 2003, 23:15:48
Ort: Västerås
Kontakt:

Inlägg av EagleSpirit »

hmm, nu blir ju inte felet hälften så stort som det borde vara men det kunde ha varit prescalern, har du konfigurerat den?
FS
Inlägg: 245
Blev medlem: 14 januari 2005, 23:35:45

Inlägg av FS »

Har nu även provat med timer1 och den ger snarlika fel som man får kompensera för genom att prova sig fram. Det blev ett fel på 41 tick (För 100us ville timer1 ha 65476 istället för 65435 som miniräknaren ville ha).

Antar att det är som cyr säger att det går åt lite instruktioner för att gå in i interruptet. Att titta på assembler koden säger mig inte mycket, tyvärr ;)

Nån add_timer finns ej.

Tur man har oscilloskop för att kontrollera timern annars hade det blivi klurigt...
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Nu har jag inte alla PIC datablad i huvudet, men har 876 en 8bits Timer2?

Det kan kanske lösa problemet isf, Timer2 brukar nämligen ha ett separat periodregister så man slipper skriva in värden varje gång.

Bara sätt periodregistret till 100 och du får interrupt var 100:e cykel.
FS
Inlägg: 245
Blev medlem: 14 januari 2005, 23:35:45

Inlägg av FS »

Jo det verkar så. Ska prova lite mer imorn. Annars är det ju bara att komma ihåg att lägga på 41 när man använder timer1.
Skriv svar