View previous topic :: View next topic |
Author |
Message |
Prasapty Guest
|
Calculating correct seconds value |
Posted: Fri Jun 10, 2005 4:30 am |
|
|
How to precise, count seconds with timer 1 (16Bit ) running on 8 MHZ:
8000000/(4*1*65536) will give 30.51 but then
ints_per_second=30.51
if(sec==60){
sec=0;
}
will give wrong second counting?
main(){
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
} |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Jun 10, 2005 6:11 am |
|
|
Been discussed about a billion times. Try the search feature. |
|
|
valemike Guest
|
|
Posted: Fri Jun 10, 2005 7:24 am |
|
|
I don't get it. Don't you have a TIMER1 isr |
|
|
Prasapty Guest
|
|
Posted: Fri Jun 10, 2005 9:28 am |
|
|
I search the forum ( RTC,TIMERS) and most of the post end in my part of the question. Maybe i miss something. Am sorry but i can't find it...
Im using clock_isr()
#INT_TIMER1
void clock_isr()
{
...
}
void main ()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
...
} |
|
|
valemike Guest
|
|
Posted: Fri Jun 10, 2005 10:05 am |
|
|
Look at CCS's example code directory at ex_stwt1.c
It shows you how to calculate how many interrupts per second (the example uses 20MHz, but you should be able to calculate it for 8MHz), sets up Timer1 properly, turns on Timer1, and shows a simple ISR. It also shows that you have to enable your timer interrupt to make the isr run.
As for your specific application, you should track your sec variable in your main loop. |
|
|
valemike Guest
|
p.s. |
Posted: Fri Jun 10, 2005 10:07 am |
|
|
From reading your code snippet, you're probably not enabling your timer1 interrupt. It also looks like you're not initializing secs to 0, etc. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Jun 10, 2005 11:05 am |
|
|
I think he is referring to the error encountered from
ints_per_second=30.51
I would use timer2 to do this or use the CCP module (if you have one) to generate an int at a certain count and have the CCP module setup to automatically reset the timer. |
|
|
Prasapty Guest
|
|
Posted: Sat Jun 11, 2005 3:33 am |
|
|
Code: |
#define ints_per_second = 30.51
int sec,min,hour;
int8 int_count;
#INT_TIMER1
void clock_isr()
{
if(--int_count==0)
{
++sec;
int_count = INTS_PER_SECOND;
if(sec==60){
sec=0;
min++;
}
if(min==60){
min=0;
hour++;
}
}
}
void main ()
{
int count;
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
lcd_init();
for (count=0; count<1000; count++)
{
printf(lcd_putc,"\f%u",sec);
delay_ms(500);
}
}
|
With this i get cca double or more, faster seconds time count ?
I want to test this on timer1.
How is this possible, to get such faster time count, if the math is right?
How to correct this? |
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Sat Jun 11, 2005 8:26 am |
|
|
Prasapty wrote: | Code: |
#define ints_per_second = 30.51
|
With this i get cca double or more, faster seconds time count ?
I want to test this on timer1.
How is this possible, to get such faster time count, if the math is right?
How to correct this? |
Quote: |
I think he is referring to the error encountered from
ints_per_second=30.51
|
Mark's previous post gives a hint why you are not getting the desired results. Furthermore, please post your #use delay statement. Also compare what your declaration for int_count is versus how you declare INTS_PER_SECOND. (Hint: one is a float; one is an integer) |
|
|
Prasapty Guest
|
|
Posted: Sun Jun 12, 2005 6:35 am |
|
|
#use delay(clock=8000000)
I changed int_count to BYTE.
The timer1 is now cca 6 seconds SLOWER then real time.
Real time : 0 - 10 -- 16 second
Timer1 : 0 - 10 -- 10 seconds
Is this becuse of the schrinked decimal ( just 2 ) places in the ints_per_second ? |
|
|
valemike Guest
|
|
Posted: Sun Jun 12, 2005 7:06 am |
|
|
exactly! try #define INTS_PER_SECOND 30 (rather than 30.51).
You cannot assign a float to an int and expect it to get truncated correctly. Otherwise you have to cast it. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Jun 12, 2005 8:26 am |
|
|
You aren't going to be accurrate the way you are doing it. Read my earlier post about the other timers. They would give you the accuracy much easier than trying to do it your ways. in_count should be declared as an int8. It was your reload value that is wrong (as MikeV stated). If you insist on doing it your way, this will give you better accuracy
Code: |
#define INTS_PER_2_SECOND = 71
int sec,min,hour;
int8 int_count = INTS_PER_2_SECOND;
#INT_TIMER1
void clock_isr()
{
int_count--;
if ((int_count==0) || (int_count==31))
{
sec++;
if (int_count==0)
int_count = INTS_PER_2_SECOND;
if(sec==60)
{
sec=0;
min++;
if (min==60)
{
min=0;
hour++;
}
}
}
}
|
|
|
|
Prasapty Guest
|
|
Posted: Sun Jun 12, 2005 9:47 am |
|
|
I understand what you want to do and it's allmost unbelivable but...
Real time 0 -- 10 --> 20 seconds
Timer time 0 -- 10 --> 10 seconds
He is now loosing over 10 seconds ( and i have to wait cca 2 second until he starts to count from 0).
Can you point me to your post where you have solved this problem ?
Anyway how is this possible? If you have 61.02 ( 2 seconds_ints ) which should be very near 30.51... How can this be that he is now loosing more time then before ?? I check this 7 times... |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Jun 12, 2005 4:06 pm |
|
|
Post a complete test program |
|
|
Prasapty Guest
|
|
Posted: Mon Jun 13, 2005 3:10 am |
|
|
Code test with internal HS on 8 MHZ:
Code: |
#include <16F877.h>
#use delay(clock=8000000)
#fuses HS, NOWDT, PUT
#include "LCD.C"
int sec,min,hour;
int8 int_count = 61;
#INT_TIMER1
void clock_isr()
{
int_count--;
if ((int_count==0) || (int_count==31))
{
sec++;
if (int_count==0)
int_count = 61;
if(sec==60)
{
sec=0;
min++;
if (min==60)
{
min=0;
hour++;
}
}
}
}
void main()
{
int i;
sec=0;
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
lcd_init();
while(TRUE)
{
printf(lcd_putc,"\f%u",sec);
delay_ms(300);
}
} |
|
|
|
|