View previous topic :: View next topic |
Author |
Message |
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
Problems with Timer1 |
Posted: Thu Apr 12, 2018 11:44 am |
|
|
Hello
I am designing a controller and I need to set the sampling time at 10ms. For this I use the TMR1 but the period is not stable, on the contrary, it is quite random.
My code is the following:
Code: |
#include<16f887.h>
#use delay (clock = 8MHz)
#fuses INTRC_IO, NOWDT, NOBROWNOUT, NOLVP, NODEBUG
#use fast_io(c)
#bit TMR1ON=0x10.0 // TMR1ON bit of T1CON identifier
#bit TMR1E = 0x8c.0
int1 b_10ms = 1;
void main()
{
set_tris_c(0x77); // 01110111
setup_adc_ports( NO_ANALOGS );
setup_oscillator(OSC_8MHZ);
delay_ms(1000);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
output_low(PIN_B1);
setup_timer_0(T0_INTERNAL | T0_DIV_32);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(45534);//
for(;;)
{
output_bit(PIN_C7, b_10ms); // Visualizo b_10ms en PIN_C7
while(!b_10ms){}; // espero la interrupciĆ³n
output_bit(PIN_C7, b_10ms);
b_10ms = 0;
}
}
#int_timer1
void clock_isr()
{
E = 0;
TMR1ON = 0;
b_10ms = 1;
set_timer1(45534);
TMR1ON = 1;
} |
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Thu Apr 12, 2018 12:28 pm |
|
|
You can't assume that the processor "will always" execute the interrupt at precisely the same time after the interrupt "fires". Depending on what other things are executing, sometimes it may be relatively quick, sometimes it may be relatively slow.
With this in mind, you should read the timer's count, add an offset to it, then write this new value to the timer.
That's one. Two, think about how you coded things. You initially set your b_10ms flag high. Then when you get to your infinite loop, you initially set PIN_C7 high. Your while() loop gets skipped because b_10ms is still high. Then you immediately set PIN_C7 low and you then set b_10ms low as well before heading through the loop again. Also, repeat after me, I will never, EVER, set a flag both within and outside an interrupt service routine. EVER.
Just get rid of the 4 lines in your infinite loop. Comment them out. Add this to the end of your ISR:
output_toggle(PIN_C7);
Even without changing the way you set timer 1 in the ISR, you should notice a much more stable waveform on PIN_C7. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Apr 12, 2018 12:35 pm |
|
|
How much variation in period are you getting?
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Mon Apr 16, 2018 12:53 am |
|
|
If you want an accurate 10mSec tick, then use timer2.
Code: |
setup_timer_2(T2_DIV_BY_16, 249, 5); //will give an interrupt at
//FOSC/(4 * 16 * 250 * 5) = 100Hz
|
Setting a timer 'to' a value is always slightly inaccurate. However the variation should not be large. It should be occurring slightly 'slow' as the timer loses the prescaler and count that have already occurred up to the point where you set the timer. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Mon Apr 16, 2018 7:23 am |
|
|
As a further comment, the value you are using is wrong anyway. The timer counts to 65535, and then wraps back (and interrupts) when effectively it counts to 65536. For a Fosc/4 (2Mhz) clock to the oscillator, you would need 20000 counts, so preload to 45536.
The correct syntax in the timer1 interrupt would be:
set_timer1(get_timer1()+45536);
To increment it by 45536. |
|
|
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
|
Posted: Mon Apr 16, 2018 8:01 am |
|
|
Thanks to everybody
I found the problem. If I simulate with 5 ms time scale, the read on the scope is ok, in others scales the reading begins to be unstable. I don't know why, but it happens this way.
Now I'll make it in a protoboard. I'll tell you about the results. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Mon Apr 16, 2018 9:17 am |
|
|
re:
I found the problem. If I simulate with 5 ms time scale
'simulate' ? as in Proteus ?? |
|
|
|