|
|
View previous topic :: View next topic |
Author |
Message |
xindy Guest
|
ex_patg question.. |
Posted: Tue Mar 04, 2008 3:49 am |
|
|
just a question about the ex_patg example.. Code: |
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
#define NUM_OUTPUTS 7
//NOTE: periods MUST be multiples of 400
//Periods are in microseconds
#define PERIOD_0 400
#define PERIOD_1 800
#define PERIOD_2 1600
#define PERIOD_3 2000
#define PERIOD_4 20000
#define PERIOD_5 64000
#define PERIOD_6 2000000
const long wave_period[NUM_OUTPUTS] = {
PERIOD_0/400, PERIOD_1/400, PERIOD_2/400, PERIOD_3/400,
PERIOD_4/400, PERIOD_5/400, PERIOD_6/400};
long counter[NUM_OUTPUTS] = {0,0,0,0,0,0,0};
int port_b_image;
// This interrupt is used to output the waveforms. The interrupt
// is automatically called ever 200us.
#INT_TIMER1
void wave_timer() {
int i;
set_timer1(0xFC4F); // sets timer to interrupt in 200us
output_b(port_b_image); // outputs the waveform
for(i=0; i<NUM_OUTPUTS; i++) // sets up next output for each pin
{
if((++counter[i]) == wave_period[i]) // if counter is expired
{
counter[i] = 0; // reset counter
if(bit_test(port_b_image,i)) // and set pin as needed
bit_clear(port_b_image,i);
else
bit_set(port_b_image,i);
}
}
}
void main() {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // setup interrupts
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
port_b_image=0; // initialize variable
output_b(port_b_image);
while(TRUE); // loop forever
}
|
why is it that in the code above, it will interrupt every 200 us? i tried to do the math but i cant figure out how it arrives at 200 us.. please help.. thanks guys.. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Mar 04, 2008 5:52 am |
|
|
Quote: | why is it that in the code above, it will interrupt every 200 us? i tried to do the math but i cant figure out how it arrives at 200 us.. | At 20MHz every instruction clock cycle takes 20Mhz / 4 = 0.2us.
Timer1 in this program is setup to use no prescalers, i.e. it is dividing by 1 Code: | setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // setup interrupts
| This results in timer1 ticking with a speed of 1 tick every 0.2us.
An interrupt will be generated when the 16-bit timer overflows from 0xFFFF to 0x0000. Without modifications this would take 0.2us * 0x10000 = 13.1ms.
Now have a look at the start of the interrupt routine: Code: | set_timer1(0xFC4F); // sets timer to interrupt in 200us
| The trick here is that timer1 is assigned a new start value which causes the next timer overflow to happen much sooner, after:
0x10000 - 0x0FC4F = 0x3B1 = 945 ticks
This is strange, I would have expected the math to come up with 1000. Most likely this deviation is there to compensate for the interrupt overhead; it takes about 40 instructions to save registers before your interrupt function is entered. I don't like the workaround here because the overhead is not a constant between processors and compiler versions, even another interrupt could cause large deviations. That's why I prefer to change this line to Code: | set_timer1( 1000 - get_timer1()); // sets timer to interrupt in 200us |
|
|
|
|
|
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
|