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 

Please go to www.mcuspace.com/mcuforum for posts concerning PIC®MCU

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

Timer based Real Time Clock (RTC)
Goto page Previous  1, 2, 3
 
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: 4

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: 162
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: 4

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: 162
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
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
Page 3 of 3

 
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