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 CCS Technical Support

modifying timer0 value dynamically

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



Joined: 10 Nov 2013
Posts: 10

View user's profile Send private message

modifying timer0 value dynamically
PostPosted: Wed Jan 22, 2014 2:25 pm     Reply with quote

hello everyone
I was trying to code a program that could produce variable timing delays on pressing the button.
Say the delay could be 5 min,10min,etc....for the first push and the subsequent pushes.
I am confused about how i can go about all this......
Also i have a doubt ....does timer0 prescalar clear itself to zero once the isr has been executed or ....???
Code:

#INCLUDE <16F877A.H>
#fuses NOWDT,NOPUT,NOLVP,NOCPD
#use delay(clock=4m)

#byte tmr0=0x01     //// timer0 address in program memory 01h

#INT_RTCC
void isr                          /// isr for 1ms interrupt
{
output_toggle(PIN_A0);   /// should i measure the output pulse time
tmr0=tmr0+6;               /// period at A0 , to get 1ms or ??
}

void main()
{
 output_a(0x00);
 setup_adc(ADC_OFF);
 setup_comparator(NC_NC_NC_NC);
 setup_psp(PSP_DISABLED);
 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); /// prescalar 1
 enable_interrupts (GLOBAL);
 enable_interrupts (INT_RTCC);

 do
 {
 output_high(PIN_A3);
 if(input(PIN_A4)==0)  //// button interface
 {tmr0=tmr0+200;       ///// dynamically changing the content of timer0
 }                                /// on button press.
 }
 while(1==1);
}
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Jan 22, 2014 4:48 pm     Reply with quote

The usual way to do this sort of thing is:-

1) Use a timer to generate say 1s ticks.
2) Count the number of ticks for a task.
3) Vary the number of ticks required as needed.

You also need to read about button debounce.

Quote:
Also i have a doubt ....does timer0 prescalar clear itself to zero once the isr has been executed or ....???
The manual tells you the conditions which reset the prescaler. End of isr is not one of them. As I understand it, the timer0 increments when its prescaler overflows, the isr is triggered when timer0 overflows, the isr routine happens somewhat later. So, at the instant when the isr is triggered, both the timer0 prescaler and timer0 will be zero, they may both have advanced by the time the isr ends.

Mike
energetic007



Joined: 10 Nov 2013
Posts: 10

View user's profile Send private message

timer0 problem
PostPosted: Thu Jan 23, 2014 12:28 am     Reply with quote

Mike, I tried to rebuild my code according to your guidance but it seems that the tick is not giving 1 second delay.
It's very annoying.
Code:

#INCLUDE <16F877A.H>
#fuses NOWDT,NOPUT,NOLVP,NOCPD
#use delay(clock=4m)

#byte tmr0=0x01

int8 tick=0;

#INT_RTCC
void isr()
{
tick++;
if(tick>=1000);  ///[b] for 1000x1.024ms =1.024 seconds delay[/b]
  {
   tick=0;
   output_toggle(PIN_A5); //// [b]i am observing this pin for req delay[/b]
  }
}

void main()
{
 output_a(0x00);
 setup_adc(ADC_OFF);
 setup_comparator(NC_NC_NC_NC);
 setup_psp(PSP_DISABLED);
 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); //  interrupt after each 1ms.
 enable_interrupts (GLOBAL);
 enable_interrupts (INT_RTCC);

 do
 {
 output_high(PIN_A3);
 }
 while(1==1);
}
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 12:50 am     Reply with quote

What is the maximum value that an int8 can hold.

Regards
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 5:10 am     Reply with quote

As a general comment, there is no point in ticking this fast.
Use /32 for the prescaler, and 122 for the counter. Means you can use an 8 bit tick counter, so quicker, and more accurate too. (4*32*256*122 = 3997696 versus 4*4*256*1000 = 4096000 - less than 0.1% error versus over 2%....).
Even better, if you are not using Timer2, use this. /16 prescale, 249 in PR2, postscale of 10, and count to 25. Exact.

Best Wishes
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 6:05 am     Reply with quote

Have a look and copy the 'software RTC' that's in the 'code library'.It's easy to adapt to your PIC and xtl nad it works ! Also very easy to add flags for say every minute or 5 minutes.

hth
jay
energetic007



Joined: 10 Nov 2013
Posts: 10

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 9:20 am     Reply with quote

i was guessing what is the use of set_timer0()
is it possible to load the timer0 register with the desired value rather than waiting for a specified number of counts to overflow and interrupt.
e.g. lets say that the timer has been loaded for an interrupt after 5 minutes but suddenly i press a button and the required value for the TMR0 gets loaded in the middle of the execution cycle despite the fact that i loose around 60 us in the interrupt handler will i be able to get a variable timer ...
say the desired value in decimal to be loaded is given by TMR0

TMR0= 256-(overflow time/(4*Tosc*prescalar))

however i corrected this program to interrupt at 1 sec.
Code:

#INCLUDE <16F877A.H>
#fuses NOWDT,NOPUT,NOLVP,NOCPD
#use delay(clock=4m)

#byte tmr0=0x01
int1 tick;
int16 count=0;

#INT_RTCC
void isr(void)
{
count++;
if(count==15)    ///  15 for 1second interrupt 1000/65.536= 15.25
  {
   count=0;
   output_toggle(PIN_A5);
  }
}

void main()
{
 output_a(0x00);
 setup_adc(ADC_OFF);
 setup_comparator(NC_NC_NC_NC);
 setup_psp(PSP_DISABLED);
 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //  interrupt after each 65.536 ms.

 enable_interrupts (GLOBAL);
 enable_interrupts (INT_RTCC);

 do
 {
  output_high(PIN_A3);
 }
 while(1==1);

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 9:45 am     Reply with quote

Yes, you can load the register, but generally for the sort of times you want, this is not the way to go.
Where you would set the timer, is for doing something where you want the timer to reset much faster than it normally can.

However in your case, you are talking about times that are a large multiple of the timer even at the slowest you are likely to run it, so instead just count.

For instance, if you have a timer ticking at 'TICKS_PER_SECOND', then have:
Code:

int16 seconds_to_wait;

#INT_WHATEVERTIMERYOUAREUSNG
void tick(void)
{
   static int8 ticks;
   if (ticks)
      --ticks;
   else
   {
      ticks=TICKS_PER_SECOND-1;
      if (seconds_to_wait)
         --seconds_to_wait;
   }
}

//Then in your main
   seconds_to_wait=HOW_LONG_YOU_WANT;
   
   do
   {
       //Things you want to do while waiting

       if (seconds_to_wait==0)
       {
           //Things you want to do after the time
           
       }
   }


Now there is a little 'important bit' here, in that the interrupt stops decrementing the counter, when it gets to zero, and the test 'seconds_to_wait==0', cannot go true, till it _is_ zero, even if the value changes during the test (think about it).

So all your button has to change is the value loaded into 'seconds_to_wait'.

Now, temtronic has advised you to look at the software RTC in the code library. Though you don't want most of this (no point in actually counting a 'time' as such), the trick this uses to allow it to tweak for different clock rates, is well worth a look.
Alternatively, as I've already said, use Timer2, which can be set to give 25 ticks per second, and will be as accurate as your CPU clock....

Best Wishes
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 9:57 am     Reply with quote

This should be the link to the working sw rtc code.

http://www.ccsinfo.com/forum/viewtopic.php?t=26177

One problem your code/PIC xtal has is accuracy ! The 4MHz xtal doesn't give a nice integer for seconds, so the 'time' will be off.
The library sw rtc code eliminates this.

It's very,very easy for your main program to setup a few 'flags' for say minutes, 5 minutes, etc. and check them every second.

I do this for a 'datalogger' that has a DS1307 RTC. The RTC sends an interrupt every second,so main 'reacts' by updating the LCD data,reading temperature sensors and saving to USB FD.Every minute a flag is set and the USB FD file is closed and reopend(hard save of data).Another flag tests for 'new day',then 'yesterday's datafile' is clsoed , 'today's datafile' opened.

hth
jay
energetic007



Joined: 10 Nov 2013
Posts: 10

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 10:16 am     Reply with quote

Ticker -= 65536;
does this mean that ticker goes all the way to zero.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Jan 23, 2014 10:21 am     Reply with quote

To zero, but never below.
If you look at the next line, if it is below 65536, it is then increased, before the next interrupt call. So it can only be 65536 or larger when the routine exits.
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