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

Timer based Real Time Clock (RTC)
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
ktallevi



Joined: 17 Dec 2005
Posts: 58

View user's profile Send private message

PostPosted: Thu Jul 22, 2010 6:24 pm     Reply with quote

Has anyone modified this to count milliseconds as well?

thanks
princejude



Joined: 07 Aug 2010
Posts: 72

View user's profile Send private message

PostPosted: Wed Aug 11, 2010 7:08 am     Reply with quote

Hello everyone, I am a student and new in CCS and C language in general. I have worked with PIC MCUs using ASSEMBLY LANGUAGE. My School project is to design and construct a DIGITAL CLOCK using PIC MCU. I modified (Mr/Engr...) ckielstra's"Timer based Real Time Clock (RTC)" code posted since Tue Feb 28, 2006 shown below to get a digital clock. The digital clock worked on proteus but the problem I have is that the first three digits are flashing ON and OFF(though there timing is correct). It is only the last digit that is permanent ON.

PLSSSSS how will I make the four digits to be ON instead of flashing ?
I will also be happy if anyone can give me materials or links on how to learn CCS (PIC C).

Here is the code posted by ckielstra

Code:

///////////////////////////////////////////////////////////
// Zero Drift Real Time Clock
// Original code supplied by Neutone.
// Some small optimizations by C.Kielstra.
///////////////////////////////////////////////////////////
#include <18F458.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,NOLVP

//RTC variables
#define XTAL_FREQUENCY  20000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // 1 clock tick = 1 instr. cycle = crystal frequency / 4
int32 Ticker;
int8 Seconds=0;

//optional:
// int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;

////////////////////////////////////////////////////////////////////////////////
// Test whether a given year is a leap year.
// This optimized version only works for the period 2001 - 2099
////////////////////////////////////////////////////////////////////////////////
#define IS_LEAP(year) (year%4 == 0)


////////////////////////////////////////////////////////////////////////////////
//    Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts( INT_TIMER1 );            // Start RTC
}

////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1                               
void TIMER1_isr()                         
{
  Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
  if ( Ticker < 65536 )                   // If second has expired
  {  Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
     seconds++;                           //   Increment number of seconds
  }

  /* --- Optional part start ---
  if(Seconds == 60) {Minutes++; Seconds=0;
    if(Minutes == 60) {Hours++; Minutes=0;
      if(Hours == 24) {Days++; Hours=0;
        if (  (Days == 29 && Month==2 && !IS_LEAP(Year))
           || (Days == 30 && Month==2)
           || (Days == 31 && (Month==4 || Month==6 || Month==9 ||   Month==11 ))
           || (Days == 32)
           ) {Month++;Days=0;}
        if(Month == 13) {Year++; Month=0;}
  }}}
   --- Optional part end ---  */
}

////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////
void main()
{
  int8 prev_second;
 
  Initialize_RTC();
  enable_interrupts( GLOBAL );

  // loop forever
  while(1)
  {
    // Toggle output every second
    if (seconds != prev_second)
    {
      prev_second = seconds;
      output_toggle(PIN_A1);
    }
  }
}



HERE IS MY MODIFIED CODE
I changed the crystal value to 25MHz (instead of 20MHz) because i did not see 20MHz in our market. Will this different crystal value affect the timing? Is my one second timing still correct?

Code:


#include <16F887.h>
#use delay(clock=25000000)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT                       //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD


//RTC variables
#define XTAL_FREQUENCY  25000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // 1 clock tick = 1 instr. cycle = crystal frequency / 4
int32 Ticker;
int8 Seconds=0;

//optional:
 int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;

////////////////////////////////////////////////////////////////////////////////
// Test whether a given year is a leap year.
// This optimized version only works for the period 2001 - 2099
////////////////////////////////////////////////////////////////////////////////
#define IS_LEAP(year) (year%4 == 0)


////////////////////////////////////////////////////////////////////////////////
//    Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts( INT_TIMER1 );            // Start RTC
}

////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////

int decode(int8 Minutes)
{
   int code;
   switch(Minutes)
   {
      case 0: code = 0x40;break;
      case 1: code = 0x79;break;
      case 2: code = 0x24;break;
      case 3: code = 0x30;break;
      case 4: code = 0x19;break;
      case 5: code = 0x12;break;
      case 6: code = 0x02;break;
      case 7: code = 0x78;break;
      case 8: code = 0x00;break;
      case 9: code = 0x10;break;
   }
   return code;
}

void main()
{
  int8 prev_second;

   int Sec_units, Min_units, Sec_tens, Min_tens;
   int Result;
   set_tris_b(0x00);
   set_tris_a(0x00);
 
  Initialize_RTC();
  enable_interrupts( GLOBAL );

  // loop forever
  while(1)
  {
    // Toggle output every second
    if (seconds != prev_second)
    {
      prev_second = seconds;

         Sec_tens = Seconds/10;
         Sec_units= Seconds%10;
           Min_tens = Minutes/10;
         Min_units= Minutes%10;

         output_A(0x02);
         Result = decode(Min_tens);
         output_C(Result);
         delay_ms(10);


         output_A(0x01);
         Result = decode(Min_units);
         output_C(Result);
         delay_ms(10);

         output_A(0x08);
         Result = decode(Sec_tens);
         output_C(Result);
         delay_ms(10);


         output_A(0x04);
         Result = decode(Sec_units);
         output_C(Result);
         delay_ms(10);

    }
  }
}

////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1                               
void TIMER1_isr()                         
{
  Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
  if ( Ticker < 65536 )                   // If second has expired
  {  Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
     seconds++;                           //   Increment number of seconds
  }

  // --- Optional part start ---
  if(Seconds == 60) {Minutes++; Seconds=0;
    if(Minutes == 60) {Hours++; Minutes=0;
      if(Hours == 24) {Days++; Hours=0;
        if (  (Days == 29 && Month==2 && !IS_LEAP(Year))
           || (Days == 30 && Month==2)
           || (Days == 31 && (Month==4 || Month==6 || Month==9 || Month==11 ))
           || (Days == 32)
           ) {Month++;Days=0;}
        if(Month == 13) {Year++; Month=0;}
  }}}
//   --- Optional part end --- 
}
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Aug 13, 2010 9:43 pm     Reply with quote

The reason your display is flickering is because you're only updating it when the seconds change. You need to update it all the time.
Quote:
I changed the crystal value to 25MHz

Check the PIC datasheet. You'll find the maximum oscillator frequency (table 17-1) is 20MHz. While you're probably OK (PICs are pretty tough), you really should use a slower crystal.
_________________
Andrew
princejude



Joined: 07 Aug 2010
Posts: 72

View user's profile Send private message

PostPosted: Tue Aug 17, 2010 7:15 am     Reply with quote

Thanks Mr Andrew, I have edited the code as follows:
1. I changed the crystal value to 4MHz.
Code:
 #use delay(clock=25000000) to  #use delay(clock=4000000)
and  #define XTAL_FREQUENCY  25000000 to #define XTAL_FREQUENCY  4000000 


2. I also changed the switch variable from Minutes to Seconds
Code:
  switch(Minutes) to switch(Seconds) 


3. I reduced the "delay_ms(10);" from 10ms to 1ms

Code:
 delay_ms(10); to delay_ms(1); 


After all these changes the FLICKERING/FLASHING/BLINKING STOPPED

I AM STILL WORKING ON THE TIME SETTING FUNCTIONS (need help if any).

I will like to use 4 push button switches labeled SET,MODE,UP and DOWN
The expected operation is as follows:

If i press the SET button - the clock will display the current time, call the MODE function(by default the MODE function will select SET_Min function) and wait for the next button to be pressed.

If i press the MODE button - it will select SET_Hr function

When the SET_Min function is selected - if i press UP button the Minutes value will increase and if i press DOWN the Minutes value will decrease.

When the SET_Hr function is selected - if i press UP button the Hours value will increase and if i press DOWN the Hours value will decrease.

Pls i need some advice (or help) on how to achieve these.

HERE IS MY CODE (the time setting section is not yet complete)

Code:
 #include <16F887.h>
#use delay(clock=4000000)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT                       //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD


#define XTAL_FREQUENCY  4000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // 1 clock tick = 1 instr. cycle = crystal frequency / 4
#define IS_LEAP(year) (year%4 == 0)
#define D 1
#define SET  PIN_D0
#define MODE PIN_D1
#define UP   PIN_D2
#define DOWN PIN_D3

int32 Ticker;
int8 Seconds=0;
int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;
// int1 flg=false;

////////////////////////////////////////////////////////////////////////////////
//    Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts(INT_TIMER1);            // Start RTC
}

/////////////////////////////////////////////////////////////////////////////////
//      Set Time
/////////////////////////////////////////////////////////////////////////////////

void set_Hr()
{
   if(!input(UP)) {enable_interrupts(INT_TIMER1); Seconds++;}
   else if(!input(DOWN)) {enable_interrupts(INT_TIMER1); Seconds--;}       
}

void set_Min()
{
   
}
   
////////////////////////////////////////////////////////////////////////////////////
//      Main Program Start Here
////////////////////////////////////////////////////////////////////////////////////

int decode(int8 Seconds)
{
   int code;
   switch(Seconds)
   {
      case 0: code = 0x40;break;
      case 1: code = 0x79;break;
      case 2: code = 0x24;break;
      case 3: code = 0x30;break;
      case 4: code = 0x19;break;
      case 5: code = 0x12;break;
      case 6: code = 0x02;break;
      case 7: code = 0x78;break;
      case 8: code = 0x00;break;
      case 9: code = 0x10;break;
   }
   return code;
}

void main()
{
  int8 prev_second;
  int Sec_units, Min_units, Sec_tens, Min_tens, Hr_units, Hr_tens;
  int Result;

  Initialize_RTC();
  enable_interrupts(GLOBAL);

  while(true)
  {
    if(!input(SET)) {disable_interrupts(INT_TIMER1); SET_Hr();}
   {
    if (seconds != prev_second)
      { prev_second = seconds; }
         {
            Sec_tens = Seconds/10;
            Sec_units= Seconds%10;
              Min_tens = Minutes/10;
            Min_units= Minutes%10;
            Hr_tens =  Hours/10;
            Hr_units=  Hours%10;

            output_A(0x20);
            Result = decode(Hr_tens);
            output_C(Result);      
            delay_ms(D);

            output_A(0x10);
            Result = decode(Hr_units);
            output_C(Result);
            delay_ms(D);

            output_A(0x02);
            Result = decode(Min_tens);
            output_C(Result);
            delay_ms(D);
   
            output_A(0x01);
            Result = decode(Min_units);
            output_C(Result);
            delay_ms(D);

            output_A(0x08);
            Result = decode(Sec_tens);
            output_C(Result);
            delay_ms(D);
   
            output_A(0x04);
            Result = decode(Sec_units);
            output_C(Result);
            delay_ms(D);
    }
  }
//   set_Hr();
}
}

////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////

#int_TIMER1                               
void TIMER1_isr()                         
{
  Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
  if ( Ticker < 65536 )                   // If second has expired
  {  Ticker += TIMER1_FREQUENCY;          // Increment ticker by clocks per second
     seconds++;                           // Increment number of seconds
  }

  if(Seconds == 60)
   {
      Minutes++; Seconds=0;
       if(Minutes == 60)
      {
         Hours++; Minutes=0;
            if(Hours == 24)
            {
               Days++; Hours=0;
                 if((Days == 29 && Month==2 && !IS_LEAP(Year))|| (Days == 30 && Month==2)
                    || (Days == 31 && (Month==4 || Month==6 || Month==9 || Month==11 ))||(Days == 32))
                  {Month++;Days=0;}
                 if(Month == 13)
                  {Year++; Month=0;}
              }   
      }         
   }
}

[/b]
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Tue Aug 17, 2010 8:26 am     Reply with quote

It's good to hear your display is working now.

Do you have any specific questions about handling your input switches? I suggest that you Google "switch debouncing" and have a read.
_________________
Andrew
hayate_kun



Joined: 22 Sep 2010
Posts: 8
Location: Malaysia

View user's profile Send private message

LCD to PIC pin connection
PostPosted: Fri Nov 12, 2010 3:57 am     Reply with quote

Hello!

I've tried the code above and it can be programm well without any error.
However, i might have connected it wrongly because the LCD doesn't display the character.

Can some one please check my connection? Thank you.
(I'm using PIC16F877A)

pin 1 to GND
pin 2 to +5V
pin 3 to GND
pin 4 to RB1
pin 5 to RB2
pin 6 to RB0
pin 7 to -
pin 8 to -
pin 9 to -
pin 10 to -
pin 11 to RB4
pin 12 to RB5
pin 13 to RB6
pin 14 to RB7
pin 15 to +5V
pin 16 to GND

SCL (DS1307) to RC3
SDA (DS1307) to RC4
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Nov 12, 2010 5:37 am     Reply with quote

For most LCD modules, pin 3 is the contrast input and should be something in the order of 0.8V, not GND as you have shown. Typically you have a 10-20K trimpot connected to +5V and GND (pins 1 and 2), and the center wiper connecting to the contrast (pin 3).
_________________
Andrew
hayate_kun



Joined: 22 Sep 2010
Posts: 8
Location: Malaysia

View user's profile Send private message

PostPosted: Fri Nov 12, 2010 7:00 am     Reply with quote

Thank you Mr. Andrew,

I've connected pin 3 to the center wiper of the trimpot and pin 1 & 2 to +5V and GND. The LCD is on and I can varies the level of contrast with nothing to be displayed! Is there something in the code that I should alter if I'm using PIC 16F877A?

Please take a look at my code:
Code:

#include <16F877A.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,NOLVP

#define use_portb_lcd TRUE
#include <lcd.c>

#byte PORTA=5
#byte PORTB=6
#byte PORTC=7
#byte PORTD=8
#byte PORTE=9

//RTC variables
#define XTAL_FREQUENCY  20000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // 1 clock tick = 1 instr. cycle = crystal frequency / 4
int32 Ticker;
int8 Seconds=0;

//optional:
// int8 Year=0,Month=0,Days=0,Hours=0,Minutes=0;

////////////////////////////////////////////////////////////////////////////////
// Test whether a given year is a leap year.
// This optimized version only works for the period 2001 - 2099
////////////////////////////////////////////////////////////////////////////////
#define IS_LEAP(year) (year%4 == 0)


////////////////////////////////////////////////////////////////////////////////
//    Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts( INT_TIMER1 );            // Start RTC
}


////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1
void TIMER1_isr()
{
  Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
  if ( Ticker < 65536 )                   // If second has expired
  {  Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
     seconds++;                           //   Increment number of seconds
  }


}

////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////
void main()
{
   int8 prev_second;

   set_tris_a(0b00111111);
   set_tris_b(0b00000000);
   set_tris_c(0b00000000);
   lcd_init();


  Initialize_RTC();
  enable_interrupts( GLOBAL );

  // loop forever
  while(1)
  {
    // Toggle output every second
    if (seconds != prev_second)
    {
      prev_second = seconds;
      output_toggle(PIN_A1);
    }
  }
}
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Nov 12, 2010 8:37 am     Reply with quote

lcd_init() clears the display, but then you don't call any functions to send characters to the screen, so of course it will remain blank!
_________________
Andrew
hayate_kun



Joined: 22 Sep 2010
Posts: 8
Location: Malaysia

View user's profile Send private message

PostPosted: Sat Nov 13, 2010 6:14 am     Reply with quote

Thank you Mr Andrew, now i can see the display. I've added the following code:

////////////////////////////////////////////////////////////////////////////////
// Example program for using the RTC
////////////////////////////////////////////////////////////////////////////////
void main()
{
int8 prev_second;

set_tris_a(0b00111111);
set_tris_b(0b00000000);
set_tris_c(0b00000000);
lcd_init();


Initialize_RTC();
enable_interrupts( GLOBAL );

// loop forever
while(1)
{
// Toggle output every second
if (seconds != prev_second)
{
prev_second = seconds;
output_toggle(PIN_A1);
printf(lcd_putc,"\nTime:%d",prev_second); }
}
}


But, why it counted from 0 till 128?and then went down to -128 to 0?
and, can you explain what is output_toggle(PIN_A1); mean?
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Sat Nov 13, 2010 9:28 am     Reply with quote

%d is for signed numbers, you want %u. See the CCS manual/help for the printf function.
Code:
output_toggle(PIN_A1);
is toggling pin A1 on and off every second, I presume for debugging purposes.
_________________
Andrew
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Thu Dec 16, 2010 3:22 pm     Reply with quote

I'm using a 18f4520 running at 20Mhz.
so I have this code
Code:
#use delay(clock=20000000)
#define XTAL_FREQUENCY  20000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // 1 clock tick = 1 instr. cycle = crystal frequency / 4

in the beginning,
then
Code:
////////////////////////////////////////////////////////////////////////////////
//    Initialize RTC
////////////////////////////////////////////////////////////////////////////////
void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts( INT_TIMER1 );            // Start RTC
}
////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////
#int_TIMER1                               
void TIMER1_isr()                         
{
  Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
  if ( Ticker < 65536 )                   // If second has expired
  {  Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
     seconds++;                           //   Increment number of seconds
  }
}


This used to work. I switched from a 452 to an LF4520. There were lots of changes in code after changing processors, but I just noticed the time is off. Now it seems to run at 33% of normal speed. What could I have done to mess it up? I'm also using other timers in my code, could this have done something? I'm sure I could tweak the numbers to make it work, but I want to know how I messed it up. Any help will be greatly appreciated.
Ringo
_________________
Ringo Davis
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Thu Dec 16, 2010 11:09 pm     Reply with quote

Your code looks fine to me. Are you disabling interrupts elsewhere in your code - that might be delaying your timer1 interrupt.
_________________
Andrew
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Fri Dec 17, 2010 7:56 am     Reply with quote

I'm disabling int#2, I'm not messing with #1 anywhere. Mostly what I'm doing is is reading an I2C sensor and printing stuff on an LCD. Actually while it is displaying the time I'm not even messing with Timer 2.
I am using a bootloader, would that matter in any way?

I read the I2C sensor then do a delay_ms(710). That works out so that I'm reading the sensor once per second and updating the LCD. I see the LCD blink 2-3 times for each time the seconds are updated, so it looks to me like the rest of the code is running at the right speed, just not the time part.
Ringo
_________________
Ringo Davis
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Fri Dec 17, 2010 1:26 pm     Reply with quote

I stripped my code down to almost nothing.
After everything is initialized I have a main loop that does this

Code:
printf(lcd_putc"\f%ld:0%d\n",TotalMinutes,Seconds);
printf("%ld:0%d\n",TotalMinutes,Seconds);
delay_ms(1000);


This code results in a time that runs at about 10% of the intended speed. Taking out the delay_ms seems to fix the problem.
Does the delay command use timer1? Is there a way around this issue? I use delay_ms in a bunch of places.

Ringo
_________________
Ringo Davis
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4  Next
Page 3 of 4

 
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