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

need help on timer0?

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



Joined: 29 Dec 2003
Posts: 81

View user's profile Send private message

need help on timer0?
PostPosted: Mon Dec 29, 2003 2:21 am     Reply with quote

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?
PostPosted: Mon Dec 29, 2003 3:28 am     Reply with quote

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

View user's profile Send private message

Re: need help on timer0?
PostPosted: Mon Dec 29, 2003 4:49 pm     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 29, 2003 7:19 pm     Reply with quote

That symbol is the letter 'L'. It just tells the compiler how to treat the constant.
chingB



Joined: 29 Dec 2003
Posts: 81

View user's profile Send private message

PostPosted: Tue Dec 30, 2003 1:14 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 30, 2003 1:30 am     Reply with quote

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







PostPosted: Tue Dec 30, 2003 4:31 am     Reply with quote

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

View user's profile Send private message

Re: need help on timer0?
PostPosted: Tue Dec 30, 2003 9:43 am     Reply with quote

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







PostPosted: Wed Jan 21, 2004 2:08 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 21, 2004 5:25 pm     Reply with quote

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;
}
}
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