CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problems with Timer1

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rfjhh



Joined: 31 Mar 2011
Posts: 51
Location: Mexico

View user's profile Send private message

Problems with Timer1
PostPosted: Thu Apr 12, 2018 11:44 am     Reply with quote

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: 1900

View user's profile Send private message

PostPosted: Thu Apr 12, 2018 12:28 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Apr 12, 2018 12:35 pm     Reply with quote

How much variation in period are you getting?

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Mon Apr 16, 2018 12:53 am     Reply with quote

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: 19215

View user's profile Send private message

PostPosted: Mon Apr 16, 2018 7:23 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Apr 16, 2018 8:01 am     Reply with quote

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: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Apr 16, 2018 9:17 am     Reply with quote

re:
I found the problem. If I simulate with 5 ms time scale

'simulate' ? as in Proteus ??
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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