|
|
View previous topic :: View next topic |
Author |
Message |
ljbeng
Joined: 10 Feb 2004 Posts: 205
|
PIC2620, TIMER0 and Major latencies |
Posted: Mon Aug 22, 2005 9:11 am |
|
|
I don't think my problem was very well understood the last time so I have simplified it down to just TIMER0 interrupt running and nothing else happening. I set TIMER0 to increment from PIN_A4. I preset TIMER0 to 255 so it overflows every pulse from PIN_A4. I then just want to time the amount of time PIN_A4 is high. There is major interrupt latency and even inside my interrupt routine, I have major delays that I cannot account for. See my comments and the jpeg logic scope picture for more details.
Code: | #include <18F2620.h>
#device ICD=TRUE
#device adc=8
#fuses WDT,WDT128,HS, NOPROTECT, IESO, NOBROWNOUT, BORV21, NOPUT, NOCPD, STVREN, NODEBUG, LVP, NOWRT, NOWRTD, NOEBTR, NOCPB, NOEBTRB, NOWRTC, NOWRTB, FCMEN, XINST, NOPBADEN, LPT1OSC, MCLR
#use delay(clock=4096000)
int16 voltcnt;
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#int_TIMER0
TIMER0_isr(){
// h11aa1 is connected to 120VAC line. Low voltage side is pulsing pin_a4.
// Interrupt occurs every 8.3333ms at zero crossing of AC line.
// Ra4 input increments timer0. Set timer0 to 255 so next pulse on ra4
// will cause overflow interrupt. Check width of 2nd pulse on every interrupt.
// Pulse gets wider as voltage drops.
//from time pin_a4 goes high to this interrupt starting is 164us or 167 instructions
//see A->B on jpeg
output_high(pin_a0);
disable_interrupts(int_timer0);
voltcnt = 0;
//wait here if interrupt started in mid high pulse...
while(input(pin_a4)){//ignore this pulse that caused interrupt
output_toggle(pin_a0);//pulse a0 many times for digital scope so
//we know which a4 pulse started the interrupt.
}
output_low(pin_a0);
while(!input(pin_a4)) restart_wdt();
//Between these two line is where my program sees a 121us delay from the time
//pin_a4 goes high to when pin_a0 goes high. Thats 123 instructions.....
//see X->Y on jpeg
output_high(pin_a0);
voltcnt = 0;
while(input(pin_a4)){
voltcnt++;
}
output_low(pin_a0);
sout:
set_timer0(255);
enable_interrupts(int_timer0);
}
void main()
{
set_tris_a(0b00010000);
set_tris_b(0b00011011);
set_tris_c(0b10000000);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_spi(FALSE);
setup_wdt(WDT_ON);
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_8_bit);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_timer0(0xff);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
#asm
bsf 0xfd5.3 //turn off prescaler assignment for timer0
#endasm
while(1) {
restart_wdt();
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 22, 2005 9:41 am |
|
|
Start by proving that the chip is running at 4.096MHz. Write a minimum program to raise a pin, wait a defined time, and lower it. It for some reason the clock is perhaps only running at 1/4 the rate you expect, all will be explained. The 'expected' latency will be about 25 to 30 instruction times to the start of the routine, to alllow for the processor saving the required registers, and then vectoring to the handler. If the clock was only about 1MHz, this would give the sort of time you are seeing. You don't need to disable the interrupt in the handler. The GIE flag is always cleared when the interrupt is responded to.
Best Wishes |
|
|
ljbeng
Joined: 10 Feb 2004 Posts: 205
|
|
Posted: Mon Aug 22, 2005 9:51 am |
|
|
You see where I output_toggle(pin_a0)? Well here is what the logic analyzer says:
X->Y is 4.89uS and I see 4 instructions in the listing. Each instruction should be .977us. 4.89us/.977us is 5 instructions. Isn't that interesting.
Code: | .................... voltcnt = 0;
00A2: CLRF 19
00A4: CLRF 18
.................... //wait here if interrupt started in mid high pulse...
....................
.................... while(input(pin_a4)){//ignore this pulse that caused interrupt
00A6: BTFSS F80.4
00A8: BRA 00AE
.................... output_toggle(pin_a0);//pulse a0 many times for digital scope so
00AA: BTG F89.0
.................... //we know which a4 pulse started the interrupt.
.................... }
00AC: BRA 00A6
.................... output_low(pin_a0);
00AE: BCF F89.0
|
|
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 22, 2005 10:15 am |
|
|
No, that is exactly right. you need to count 'cycles', not instructions. The BRA instuction takes two cycles to execute.
How is your ICD setup?. This can add latencies, since it involves calling extra code in high memory on programmed events. Disable it and run the timings again.
Best Wishes |
|
|
ljbeng
Joined: 10 Feb 2004 Posts: 205
|
|
Posted: Mon Aug 22, 2005 12:01 pm |
|
|
Nothing.
Disabled ICD=TRUE and programmed the chip. I still see the delays.
I will try an 18F252 and see what it does..... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 22, 2005 12:18 pm |
|
|
Quote: | #fuses WDT,WDT128,HS, NOPROTECT, IESO, NOBROWNOUT, BORV21, NOPUT, NOCPD, STVREN, NODEBUG, LVP, NOWRT, NOWRTD, NOEBTR, NOCPB, NOEBTRB, NOWRTC, NOWRTB, FCMEN,
XINST, NOPBADEN, LPT1OSC, MCLR |
Are you really using a Low Voltage programmer ? Your code says ICD.
ICD and ICD2 are High Voltage programmers. They need NOLVP, not LVP.
Does CCS support the Extended Instruction set ? We've had people
report in the past that PCWH was enabling that fuse by default, and
that their code crashes because of it. See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=23072&highlight=xinst
Do you need the watchdog timer running while you're trouble-shooting
a timer problem ? It will just add one more unknown factor into the
problem. |
|
|
sseidman
Joined: 14 Mar 2005 Posts: 159
|
|
Posted: Mon Aug 22, 2005 12:19 pm |
|
|
ljbeng wrote: | Nothing.
Disabled ICD=TRUE and programmed the chip. I still see the delays.
I will try an 18F252 and see what it does..... |
While you're in the process of debugging this, why don't you turn off the watchdog timer? Pare things down to the most basic code you possibly can.
Also, don't center your experiments arount this "1 clock tick" experiment. Speed up your clock by an order of magnitude, and use 10 or 20 clock ticks-- then try to assess the delays.
Also, someone pointed out a few months ago that set_timer0(xxx) will produce many more delays than adding xxx to the value in timer0. This is pretty tough if you're only allowing yourself 1 clock tick to accomplish anything. If you give yourself more ticks, you might not need to disable the interrupt in the handling routine, which is something I would try to avoid (though I'm not sure why--it just seems ill advised). |
|
|
ljbeng
Joined: 10 Feb 2004 Posts: 205
|
|
Posted: Mon Aug 22, 2005 12:26 pm |
|
|
Well, a 16F873A does the same thing. I think the Logic analyzer calls it high before the processor does. PIN_A4 is ST so it has to be >.8*5V or 4.0V. So the logic analyzer may be picking up the voltage level as high before the chip does. There may be no problem here.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|