Unfortunately, this example will not produce an accurate timebase. When you clear TMR0 each second you loose two cycles plus any counts accumulated in the prescaler. It may only be six or eight or ten cycles lost each second, but the error is cumulative and measurable.Hmm. I made one such circuit, a LED display minute counter, based on 32 KHz crystal. This is 8,192 clocks per second.MMcLaren said:Unfortunately, any write to TMR0, including clearing of bit 7, causes the prescaler to be reset, if you're using it, and also causes TMR0 to pause for 2 instruction cycles before it starts counting again.
Caveat! This may not be a very good method for "correct accuracy".
The prescaler is set to 0x07 (256). So it is 32 clocks per second.
In the main loop I test for 0x20:
Then I increment the seconds counter:Rich (BB code):if (TMR0==0x20)add_sec();
I don't observe a resetting of the prescaler. Or I misunderstand something! I examined the source right now, it is just some lines C.Rich (BB code):void add_sec() { TMR0=0; time_secs1++; if(time_secs1==10){time_secs1=0;time_secs10++;}; if(time_secs10==6){time_secs10=0;time_mins1++;}; if(time_mins1==10){time_mins1=0;time_mins10++;}; if(time_mins10==6){time_mins10=0;}; }
Also I don't observe any inaccuracy. I am wondering about this for a while, since it is mentioned in the 16F5X datasheet.
You can't "observe a resetting of the prescaler" directly because we don't have direct access to the prescaler but you can measure the cumulative error empirically in simulation simply by keeping track of the number of instruction cycles between one second intervals.
I'm sure you don't want to pass on faulty advice to Robin and other forum members, but, without qualification, your advice about clearing TMR0 bit 7, and this new code example which clears TMR0, may not be very good methods for producing an accurate timebase.
Once you understand the problem, it's relatively easy to work around it. For example, all you really had to do in the example code to avoid cumulative error was to leave TMR0 "free running" and test for the recurring one second interval. Perhaps something like this;
Rich (BB code):
if (TMR0 & 0x20) add_sec(); //
while(TMR0 & 0x20); //
Rich (BB code):
void add_sec()
{
time_secs1++;
if(time_secs1==10){time_secs1=0;time_secs10++;};
if(time_secs10==6){time_secs10=0;time_mins1++;};
if(time_mins1==10){time_mins1=0;time_mins10++;};
if(time_mins10==6){time_mins10=0;};
}
Last edited: