|
|
View previous topic :: View next topic |
Author |
Message |
nicenoise
Joined: 10 May 2004 Posts: 17 Location: barcelona
|
timer1 problem...!!! |
Posted: Fri Nov 26, 2004 7:33 pm |
|
|
hello,
i need a pwm output with low frequency....
and i want to do only with the timer1...
i write this program but not works...
any know what's happend??
i dont know what is the exactly time of the timer... for example, i need 10Hz, what's the number that i have to put into the instruccion "set_timer1()"? this time have to be multiplied with 100... because de complete cycle are 100 overflows...
thanks
Alex
Code: |
#include <16F628.h>
#fuses HS,NOWDT,NOPROTECT,NOMCLR,NOBROWNOUT, NOLVP
//#use fixed_io(a_outputs=PIN_A2, PIN_A3)
#use delay(clock=20000000)
//#use rs232(baud=31250, xmit=PIN_A1, parity=N, bits=8)
int overflow=0;
int duty;
#int_timer1
void isr() {
set_timer1(0); // time overflow = 65000*0.2us ???
overflow++;
if(overflow==duty)
output_bit(pin_b3,1);
if(overflow==(100-duty)){
output_bit(pin_b3,0);
overflow=0;
}
}
main() {
byte duty;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
while (TRUE) {
duty = 50;
output_bit(PIN_A2, 1);
delay_ms(500);
output_bit(PIN_A2, 0);
delay_ms(500);
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Sat Nov 27, 2004 5:26 am |
|
|
First comment. Setting a timer as shown, will allways give timing errors. The reason is that an interrupt is not 'instantaneous'. It'll take about 30 to 40 machine cycles to actually reach the command to set the time, so the loop will run slow. Ideally use a prescaler/crystal, that gives the required rate without setting the timer. Using the hardware CCP, is a 'better' solution to reset the timer.
Second comment. The reason it does not work at present, is the comparisons in the timer interrupt. The first one sets the output when the counter (overflow) gets to 50. The second, then immediately resets the output (100-50 = 50...).
Use this:
Code: |
#int_timer1
void isr() {
if(++overflow==duty)
output_bit(pin_b3,1);
if(overflow==100){
output_bit(pin_b3,0);
overflow=0;
}
}
|
As it stands, this will give a 'step time', of 0.2E-6 * 65536 seconds = 0.0131 seconds. 1.31 seconds for the complete cycle.
If you want to set the timer 'forward', to give a faster loop, then you will have to accept that there will be inaccuracies (depending to a large extent on what else the chip is doing). You can either read th current timer value, and add a constant to this (this will reduce the inacuracy is another interrupt has occurred), or just load with a fixed value.
So to get '10Hz', would require the interrupt at 1KHz, and the timer to have 65536-5000 added. If you 'guess' at the interrupt latency, as 40 cyles, then using:
set_timer1(65536-4960);
Should be very close, but will go into error, is other interrupts occur.
set_timer1(get_timer1()+(65536-5000));
Will only be in error by a few of instruction times (the time needed to fetch the timer, add the value, and write it back). This could potentially be adjusted out by changing the value to compensate (probably to about 65536-4992).
Best Wishes |
|
|
|
|
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
|