Sida 1 av 1
Timer interrupt problem
Postat: 22 januari 2005, 17:51:01
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);
}
Postat: 22 januari 2005, 18:20:14
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...
Postat: 22 januari 2005, 18:32:04
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
Postat: 22 januari 2005, 22:33:34
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);
}
Postat: 22 januari 2005, 23:07:02
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å?
Postat: 22 januari 2005, 23:11:01
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?
Postat: 22 januari 2005, 23:22:15
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...
Postat: 22 januari 2005, 23:26:10
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.
Postat: 22 januari 2005, 23:38:09
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.