View previous topic :: View next topic |
Author |
Message |
energetic007
Joined: 10 Nov 2013 Posts: 10
|
modifying timer0 value dynamically |
Posted: Wed Jan 22, 2014 2:25 pm |
|
|
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
|
|
Posted: Wed Jan 22, 2014 4:48 pm |
|
|
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
|
timer0 problem |
Posted: Thu Jan 23, 2014 12:28 am |
|
|
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
|
|
Posted: Thu Jan 23, 2014 12:50 am |
|
|
What is the maximum value that an int8 can hold.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Jan 23, 2014 5:10 am |
|
|
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: 9255 Location: Greensville,Ontario
|
|
Posted: Thu Jan 23, 2014 6:05 am |
|
|
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
|
|
Posted: Thu Jan 23, 2014 9:20 am |
|
|
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: 19568
|
|
Posted: Thu Jan 23, 2014 9:45 am |
|
|
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: 9255 Location: Greensville,Ontario
|
|
Posted: Thu Jan 23, 2014 9:57 am |
|
|
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
|
|
Posted: Thu Jan 23, 2014 10:16 am |
|
|
Ticker -= 65536;
does this mean that ticker goes all the way to zero. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Jan 23, 2014 10:21 am |
|
|
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. |
|
|
|