|
|
View previous topic :: View next topic |
Author |
Message |
chingB
Joined: 29 Dec 2003 Posts: 81
|
need help on timer0? |
Posted: Mon Dec 29, 2003 2:21 am |
|
|
Hi
I need your comments on this code... I can't figure out on how to display a second count on an LCD display?
I got an idea from neutone but I can't figure out how?
Need your help on this....
Code: |
#include <18F452.h> // Target PIC Microcontroller IC
#device *=16 // use a 16-bit pointer
#device ICD=TRUE
#fuses HS,NOPROTECT,NOWDT // PIC MCU Configuration
#use delay(clock=20000000) // 20MHz Crystal clock speed
#include <LCD.C> // LCD routines are here
int1 ticxf = 0 ; // Timer Tic flag bit
int8 seconds=0 ;
int32 clock=19660800;
#int_timer0
timer0_isr() {
clock -= 16384;
if (clock<16384)
{
seconds++;
clock += 19660800;
ticxf = 1;
}
}
main()
{
lcd_init();
setup_counters(RTCC_INTERNAL,RTCC_DIV_128);
enable_interrupts(int_timer0); // Enable timer0 interrupt
enable_interrupts(GLOBAL); // Enable Global interrupt
while(1)
{
if (ticxf)
{
ticxf=0;
lcd_gotoxy(1,1);
printf(lcd_putc,"%02u",seconds);
}
}
}
|
Thank you. |
|
|
Ttelmah Guest
|
Re: need help on timer0? |
Posted: Mon Dec 29, 2003 3:28 am |
|
|
chingB wrote: | Hi
I need your comments on this code... I can't figure out on how to display a second count on an LCD display?
I got an idea from neutone but I can't figure out how?
Need your help on this....
Code: |
#include <18F452.h> // Target PIC Microcontroller IC
#device *=16 // use a 16-bit pointer
#device ICD=TRUE
#fuses HS,NOPROTECT,NOWDT // PIC MCU Configuration
#use delay(clock=20000000) // 20MHz Crystal clock speed
#include <LCD.C> // LCD routines are here
int1 ticxf = 0 ; // Timer Tic flag bit
int8 seconds=0 ;
int32 clock=19660800;
#int_timer0
timer0_isr() {
clock -= 16384;
if (clock<16384)
{
seconds++;
clock += 19660800;
ticxf = 1;
}
}
main()
{
lcd_init();
setup_counters(RTCC_INTERNAL,RTCC_DIV_128);
enable_interrupts(int_timer0); // Enable timer0 interrupt
enable_interrupts(GLOBAL); // Enable Global interrupt
while(1)
{
if (ticxf)
{
ticxf=0;
lcd_gotoxy(1,1);
printf(lcd_putc,"%02u",seconds);
}
}
}
|
Thank you. |
Your arithmetic is screwed for the clock rate/divider.
The timer, will be counting at 20000000/(4*128) Hz, and will interrupt every 256 counts. Hence the interrupt will occur 152.587890625 times per second. Now the 'point' of the large number, and the subtraction, is to provide a way of doing the 'fractional' counts. Basically if the numbers are chosen right, the arithmetic provides the ability to do an extra count at intervals to keep the resulting 'tick' accurate. If you multiply the interrupt frequency, by the decrementing number, you get the 'starting' count required. So in this case:
152.587890625 * 16384 = 2500000
The code then becomes (only the parts that change):
#define CLOCK_VAL (2500000l)
int32 clock=CLOCK_VAL;
#int_timer0
timer0_isr() {
clock -= 16384;
if (clock<16384)
{
seconds++;
clock += CLOCK_VAL;
ticxf = 1;
}
}
Now if you think through the cycle of this loop, the 'ticxf' flag, will be set whenever 2500000/16384 is less than 16384, and this will happen the required number of times per second. Your current values, set the flag, every 1200 interrupts, which will give a clock changing about every 8 seconds (7.86).
One seperate comment, '*=16', is not needed on the 18F family (it does nothing on the 16bit ships, they use 16bit addressing all the time). Doesn't really matter.
Best Wishes |
|
|
chingB
Joined: 29 Dec 2003 Posts: 81
|
Re: need help on timer0? |
Posted: Mon Dec 29, 2003 4:49 pm |
|
|
Quote: |
#define CLOCK_VAL (2500000l)
int32 clock=CLOCK_VAL;
#int_timer0
timer0_isr() {
clock -= 16384;
if (clock<16384)
{
seconds++;
clock += CLOCK_VAL;
ticxf = 1;
}
}
|
#define CLOCK_VAL (2500000l) ----> is this a constant definition or a macro? why their is a symbol "|" a the end of the figure 2500000?
Thank you |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Dec 29, 2003 7:19 pm |
|
|
That symbol is the letter 'L'. It just tells the compiler how to treat the constant. |
|
|
chingB
Joined: 29 Dec 2003 Posts: 81
|
|
Posted: Tue Dec 30, 2003 1:14 am |
|
|
Mark wrote: | That symbol is the letter 'L'. It just tells the compiler how to treat the constant. |
Is their a big difference if I declare constant with an "l" at end? or just plain constant declaration without an 'l'?
I understand "()" is just for good coding practice.
BTW, what "l" stands for?
Thanx |
|
|
chingB
Joined: 29 Dec 2003 Posts: 81
|
|
Posted: Tue Dec 30, 2003 1:30 am |
|
|
Hello,
Here is the code for my real-time clock...
Thanx to Ttelmah and Mark for the inputs and info.
===================================
Code: |
#include <18F452.h> // Target PIC Microcontroller IC
#device *=16 // use a 16-bit pointer
#device ICD=TRUE
#fuses HS,NOPROTECT,NOWDT // PIC MCU Configuration
#use delay(clock=20000000) // 20MHz Crystal clock speed
#include <LCD.C> // LCD routines are here
#define CLOCK_VAL (78125l)
int32 clock = CLOCK_VAL;
int1 tick = 0 ; // Timer Tic flag bit
int8 seconds ; // 00 - 59 seconds
int8 minutes ; // 00 - 59 minutes
int8 hours ; // 00 - 23 hours, military format
int8 mthdays ; // 01 - 31 days in a month
int8 months ; // 01 - 12 months, 1-JAN, ..., 12-DEC
int8 years ; // 00 - 99 2-digit year within a century
int8 y2kyrs ; // 20 - 99 Y2K year or century
int8 dummy ; // scratch pad or dummy variable 1
/*****************************************************************************/
#int_timer0
timer0_isr()
{
clock -= 16384;
if (clock<16384)
{
//seconds++;
clock += CLOCK_VAL;
tick = 1;
}
}
/*****************************************************************************/
void show_date() // show date to LCD display
{
lcd_gotoxy(1,1);
switch (months)
{
case 1 : printf(lcd_putc,"JAN-%02u ",mthdays); break;
case 2 : printf(lcd_putc,"FEB-%02u ",mthdays); break;
case 3 : printf(lcd_putc,"MAR-%02u ",mthdays); break;
case 4 : printf(lcd_putc,"APR-%02u ",mthdays); break;
case 5 : printf(lcd_putc,"MAY-%02u ",mthdays); break;
case 6 : printf(lcd_putc,"JUN-%02u ",mthdays); break;
case 7 : printf(lcd_putc,"JUL-%02u ",mthdays); break;
case 8 : printf(lcd_putc,"AUG-%02u ",mthdays); break;
case 9 : printf(lcd_putc,"SEP-%02u ",mthdays); break;
case 10: printf(lcd_putc,"OCT-%02u ",mthdays); break;
case 11: printf(lcd_putc,"NOV-%02u ",mthdays); break;
case 12: printf(lcd_putc,"DEC-%02u ",mthdays); break;
default: printf(lcd_putc,"ERR-%02u ",mthdays); break;
}
}
/*****************************************************************************/
void show_time() // Show Time to LCD display
{
lcd_gotoxy(8,1);
if (hours >= 12) // "PM"
{
if (hours >= 13)
printf(lcd_putc,"%02u:%02u:%02uP", hours-12, minutes, seconds);
else
printf(lcd_putc,"%02u:%02u:%02uP", hours, minutes, seconds);
}
else // "AM"
printf(lcd_putc,"%02u:%02u:%02uA", hours, minutes, seconds);
}
/*****************************************************************************/
void update_clock() // Update Real Time Clock
{
if (seconds >= 60)
{
seconds = 0; minutes++ ;
}
if (minutes >= 60)
{
minutes = 0; hours++ ;
}
if (hours >= 24)
{
hours = 0; mthdays++ ;
}
switch (months)
{
case 2:
dummy = 28; // Feb. has 28 days alone
if ((years % 4 )==0) dummy++;
break; // Leap Year? Feb=29days
case 4: Case 6: Case 9: Case 11: dummy = 30; break;
// 4=April,6=June, 9=Sept.,11=November // have 30 days
default: dummy = 31; break; // All the rest have 31 days
}
if (mthdays > dummy) // check if new month
{
mthdays = 1; months++ ;
}
if (months > 12)
{
months = 1; years++ ;
}
if (years > 100)
{
years = 0; y2kyrs++ ;
}
//if ((seconds % 10) == 0) t10sf = 1; // set 10s flag
show_date(); // display Month and Day to LCD
show_time(); // display Time to LCD
}
/*****************************************************************************/
void init_chip() // Initialize the MCU Chip
{
lcd_init(); // LCD should be initialized first
seconds = 10 ; // 00 - 59 seconds
minutes = 38 ; // 00 - 59 minutes
hours = 11 ; // 00 - 23 hours, military format
mthdays = 30 ; // 01 - 31 days in a month
months = 12 ; // 01 - 12 months, 1-JAN, ..., 12-DEC
years = 03 ; // 00 - 99 2-digit year within a century
y2kyrs = 20 ; // 20 - 99 Y2K year or century
setup_adc_ports(NO_ANALOGS);
setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
//setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);
enable_interrupts(int_timer0); // Enable timer0 interrupt
enable_interrupts(GLOBAL); // Enable global interrupts
}
/*****************************************************************************/
main()
{
//lcd_init();
//setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
//enable_interrupts(int_timer0); // Enable timer0 interrupt
//enable_interrupts(GLOBAL); // Enable Global interrupt
init_chip();
while(1)
{
if (tick)
{
tick=0;
//lcd_gotoxy(1,1);
//printf(lcd_putc,"%02u",seconds);
update_clock();
seconds++;
}
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 30, 2003 4:31 am |
|
|
chingB wrote: | Mark wrote: | That symbol is the letter 'L'. It just tells the compiler how to treat the constant. |
Is their a big difference if I declare constant with an "l" at end? or just plain constant declaration without an 'l'?
I understand "()" is just for good coding practice.
BTW, what "l" stands for?
Thanx |
'long'.
There is a difference, if you use the constant in arithmetic. If you declare the constant with an 'l' (since it is over 255), if will force the compiler to use 'long' arithmetic in any statement involving the constant. Without this, you are dependant on automatic casting (erratic in the CCS C), and 'luck', as to how the arithmetic will behave. I allways declare 'long' constants explicitly, and it does reduce the incidence of some compiler oddities. :-)
Best Wishes |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: need help on timer0? |
Posted: Tue Dec 30, 2003 9:43 am |
|
|
chingB wrote: | Hi
I need your comments on this code... I can't figure out on how to display a second count on an LCD display?
I got an idea from neutone but I can't figure out how?
Need your help on this....
Thank you. |
timer0 (16 bit mode w/no prescaler) increments every 65536 instruction cycles
20MHz crystle = 5Mega Instructions per second
5Mips = 76.2939453125 interupts of timer 0
Interputs occur every 0.0131072 seconds
Maximum jitter in second reporting is 13mS
Long term drift is that of the chips oscilator.
Code: |
Int32 Ticker;
#int_TIMER0
void TIMER0_isr()
{ Ticker -= 65536;
if ( Ticker < 65536)
{ Ticker += 5000000;
second++;
}
}
|
|
|
|
Guest Guest
|
|
Posted: Wed Jan 21, 2004 2:08 pm |
|
|
Why is the line //setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);
commented out, yet setup_counters(RTCC_INTERNAL,RTCC_DIV_16) is not? you don't ever use RTCC interrupt... also, is there a way to reduce the number of times the interrupt is called, without affecting the clock properities, I.E. Reducing the over head? |
|
|
chingB
Joined: 29 Dec 2003 Posts: 81
|
|
Posted: Wed Jan 21, 2004 5:25 pm |
|
|
Guest wrote: | Why is the line //setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);
commented out, yet setup_counters(RTCC_INTERNAL,RTCC_DIV_16) is not? you don't ever use RTCC interrupt... also, is there a way to reduce the number of times the interrupt is called, without affecting the clock properities, I.E. Reducing the over head? |
either setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16); or setup_counters(RTCC_INTERNAL,RTCC_DIV_16) is used will provide the same result for the timer0 interrupt. The advantage of setup_counter is for compatibility of older PIC chips supported by CCS C.
for this application that will generate real-time clock.. I guess you can't use setup_timer_0(RTCC_INTERNAL | RTCC_DIV_128) and greater becuase it will give less than one interrupt.
for setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64) ----> 1.1920928955078125 interrupts using a 20MHz clock
#int_timer0
timer0_isr()
{
clock -= 65536;
if (clock<65536)
{
//seconds++;
clock += 78125;
tick = 1;
}
} |
|
|
|
|
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
|