Real-Time Clock Project

ericgibbs

Joined Jan 29, 2010
21,439
Hi Kittu,
Why are you testing for rollovers in following IF statements, if the current IF is less than the maximum value of the current test?
E
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
Hi Kittu,
Why are you testing for rollovers in following IF statements, if the current IF is less than the maximum value of the current test?
E
When a variable exceeds its maximum value, it rolls over to zero and increments the next higher-order variable.
 

ericgibbs

Joined Jan 29, 2010
21,439
hi K,
As you say IF it rolls over it increments the next higher order, but you are testing for all the following order roll-overs orders, even when a proceeding order test, has not reached the rollover value.

Simply put, your program is wasting time, testing for states that cannot have reached rollover.

Do you follow?


E
Example:

// Handle rollovers for seconds
if (seconds >= 60) {
seconds = 0;
minutes++; // assume the Seconds count is only 50 ie: not at the rollover value

// why then are you testing the Minutes for rollover?

// Handle rollovers for minutes
if (minutes >= 60) {
minutes = 0;
hours++;
 
Last edited:

Thread Starter

Kittu20

Joined Oct 12, 2022
511
hi K,
As you say IF it rolls over it increments the next higher order, but you are testing for all the following order roll-overs orders, even when a proceeding order test, has not reached the rollover value.

Simply put, your program is wasting time, testing for states that cannot have reached rollover.
Thank you for your patience. Here's the complete code with detailed comments to ensure clarity. Please take a look at the code below and let me know if you have any further questions or if there's anything specific you'd like to point out."
C:
#include <xc.h>
#include "config.h"

volatile int timeFlag = 0;
volatile unsigned char seconds = 0;
volatile unsigned char minutes = 0;
volatile unsigned char hours = 0;
volatile unsigned char days = 1;
volatile unsigned char months = 1;
volatile unsigned int years = 2023;

void initializeTimer1() {
    // Configure Timer1 in 8-bit mode with a prescaler of 8
    T1CON = 0b00110000;

    // Calculate Reload_Value for 1ms with a 20 MHz oscillator and prescaler 8
    uint16_t Reload_Value = 625; // (20,000,000 / 4 / 8) = 625

    // Configure CCP module in Special Event Trigger mode
    CCP1CON = 0b00001011; // 0x0B

    // Load the high and low bytes of Reload_Value into CCPR1
    CCPR1H = (Reload_Value >> 8); // Load high byte of Reload_Value
    CCPR1L = (Reload_Value & 0xFF); // Load low byte of Reload_Value

    // Clear Timer1 registers
    TMR1H = 0;
    TMR1L = 0;

    // Clear Timer1 interrupt flag
    TMR1IF = 0;

    // Enable Timer1 and CCP module
    TMR1ON = 1;
    CCP1IE = 1; // Enable CCP1 interrupt
}

void main() {
    // Initialize Timer1
    initializeTimer1();

    // Initialize INTCON register
    INTCON = 0; // Clear INTCON register

    // Enable global and peripheral interrupts
    INTCONbits.GIE = 1;  // Global Interrupt Enable
    INTCONbits.PEIE = 1; // Peripheral Interrupt Enable

    while (1) {

        // Check if the timeFlag is set (1ms interval)
        if (timeFlag) {
            // Increment seconds
            seconds++;

            // Handle rollover for seconds
            if (seconds >= 60) {
                seconds = 0;  // Reset seconds to 0 when it reaches 60
                minutes++;    // Increment the minutes part of the time

                // Handle rollover for minutes
                if (minutes >= 60) {
                    minutes = 0;  // Reset minutes to 0 when it reaches 60
                    hours++;      // Increment the hours part of the time

                    // Handle rollover for hours
                    if (hours >= 24) {
                        hours = 0;  // Reset hours to 0 when it reaches 24
                        days++;     // Increment the days part of the time

                        // Check for month and year changes (simplified, not accounting for leap years)
                        if (days > 30) {  // If 30 days have passed (1 month, simplified)
                            days = 1;     // Reset days to 1 to start a new month
                            months++;     // Increment the months part of the time

                            if (months > 12) {  // If 12 months have passed (1 year, simplified)
                                months = 1;  // Reset months to 1 to start a new year
                                years++;     // Increment the years part of the time
                            }
                        }
                    }
                }
            }

            // Reset the timeFlag to indicate that the 1ms interval has been processed
            timeFlag = 0;
        }
    }
}

void __interrupt() ISR() {
    if (CCP1IF) {
        // CCP1 interrupt occurred (1ms interval)
        timeFlag = 1;    // Set the timeFlag

        // Clear the CCP1 interrupt flag
        CCP1IF = 0;
    }
}
If seconds is 50, and the code executes with the condition if (seconds >= 60), it will not trigger the rollover because 50 is not greater than or equal to 60. Therefore, in this case, seconds will remain at 50, and minutes will not be incremented.

C:
if (seconds >= 60) {
    seconds = 0;
    minutes++;
}
 

ericgibbs

Joined Jan 29, 2010
21,439
If seconds is 50, and the code executes with the condition if (seconds >= 60), it will not trigger the rollover because 50 is not greater than or equal to 60. Therefore, in this case, seconds will remain at 50, and minutes will not be incremented.
Hi K,
I think you are missing my point, relook at what I stated.

// Handle rollovers for seconds
if (seconds >= 60) {
seconds = 0;
minutes++;


If the Minutes have NOT been incremented, why are you testing if (minutes >= 60)
It can only have been incremented if the Seconds had been 60

// Handle rollovers for minutes
if (minutes >= 60) {
minutes = 0;
hours++;
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
Hi K,
I think you are missing my point, relook at what I stated.
Each if statement is responsible for checking and handling rollovers for a specific time unit (e.g., seconds, minutes, hours, days, months).
C:
    while (1) {

        // Check if the timeFlag is set (1ms interval)
        if (timeFlag) {
            // Increment seconds
            seconds++;

            // Handle rollover for seconds
            if (seconds >= 60) {
                seconds = 0;  // Reset seconds to 0 when it reaches 60
                minutes++;    // Increment the minutes part of the time
            }

            // Handle rollover for minutes
            if (minutes >= 60) {
                minutes = 0;  // Reset minutes to 0 when it reaches 60
                hours++;      // Increment the hours part of the time
            }

            // Handle rollover for hours
            if (hours >= 24) {
                hours = 0;  // Reset hours to 0 when it reaches 24
                days++;     // Increment the days part of the time
            }

            // Check for month and year changes (simplified, not accounting for leap years)
            if (days > 30) {  // If 30 days have passed (1 month, simplified)
                days = 1;     // Reset days to 1 to start a new month
                months++;     // Increment the months part of the time
            }

            if (months > 12) {  // If 12 months have passed (1 year, simplified)
                months = 1;  // Reset months to 1 to start a new year
                years++;     // Increment the years part of the time
            }

            // Reset the timeFlag to indicate that the 1ms interval has been processed
            timeFlag = 0;
        }
    }
Are you suggesting this approach ?
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
Hi K,
Please post your complete Code listing, make sure I am not missing a point.
E
Here's the updated code:
C:
#include <xc.h>
#include "config.h"

volatile int timeFlag = 0;
volatile unsigned char seconds = 0;
volatile unsigned char minutes = 0;
volatile unsigned char hours = 0;
volatile unsigned char days = 1;
volatile unsigned char months = 1;
volatile unsigned int years = 2023;

void initializeTimer1() {
    // Configure Timer1 in 8-bit mode with a prescaler of 8
    T1CON = 0b00110000;

    // Calculate Reload_Value for 1ms with a 20 MHz oscillator and prescaler 8
    uint16_t Reload_Value = 625; // (20,000,000 / 4 / 8) = 625

    // Configure CCP module in Special Event Trigger mode
    CCP1CON = 0b00001011; // 0x0B

    // Load the high and low bytes of Reload_Value into CCPR1
    CCPR1H = (Reload_Value >> 8); // Load high byte of Reload_Value
    CCPR1L = (Reload_Value & 0xFF); // Load low byte of Reload_Value

    // Clear Timer1 registers
    TMR1H = 0;
    TMR1L = 0;

    // Clear Timer1 interrupt flag
    TMR1IF = 0;

    // Enable Timer1 and CCP module
    TMR1ON = 1;
    CCP1IE = 1; // Enable CCP1 interrupt
}

void main() {
    // Initialize Timer1
    initializeTimer1();

    // Initialize INTCON register
    INTCON = 0; // Clear INTCON register

    // Enable global and peripheral interrupts
    INTCONbits.GIE = 1;  // Global Interrupt Enable
    INTCONbits.PEIE = 1; // Peripheral Interrupt Enable

    while (1) {

        // Check if the timeFlag is set (1ms interval)
        if (timeFlag) {
            // Increment seconds
            seconds++;

            // Handle rollover for seconds
            if (seconds >= 60) {
                seconds = 0;  // Reset seconds to 0 when it reaches 60
                minutes++;    // Increment the minutes part of the time
            }

            // Handle rollover for minutes
            if (minutes >= 60) {
                minutes = 0;  // Reset minutes to 0 when it reaches 60
                hours++;      // Increment the hours part of the time
            }

            // Handle rollover for hours
            if (hours >= 24) {
                hours = 0;  // Reset hours to 0 when it reaches 24
                days++;     // Increment the days part of the time
            }

            // Check for month and year changes (simplified, not accounting for leap years)
            if (days > 30) {  // If 30 days have passed (1 month, simplified)
                days = 1;     // Reset days to 1 to start a new month
                months++;     // Increment the months part of the time
            }

            if (months > 12) {  // If 12 months have passed (1 year, simplified)
                months = 1;  // Reset months to 1 to start a new year
                years++;     // Increment the years part of the time
            }

            // Reset the timeFlag to indicate that the 1ms interval has been processed
            timeFlag = 0;
        }
    }
}

void __interrupt() ISR() {
    if (CCP1IF) {
        // CCP1 interrupt occurred (1ms interval)
        timeFlag = 1;    // Set the timeFlag

        // Clear the CCP1 interrupt flag
        CCP1IF = 0;
    }
}
 

JohnInTX

Joined Jun 26, 2012
4,787
A couple of things:

If you use CCP mode 0xB (special event trigger), the Reload_Value should be 624 to account for how the CCP special event trigger works. The average cycle count shown in #19 is one TMR1 count too long.
I am surprised that the cycle count varies at all. I don't know if that is an artifact of the simulator or if it is accurately showing some 'feature' of the chip. It simulates the same here on MPLABX 5.40 with your code.
I DID change the code to use @MrChips ' method of CCP mode 0x08 and manually advancing the CCP compare register. It simulated with the exact counts expected so in the absence of testing on actual hardware, I'd use that method instead of the special event trigger. In the interrupt code just add the line:
CCPR1 += Reload_Value; // advance CCP count by 1ms
You can also use the same construct for initializing instead of calculating the individual bytes.

Nits:
timeFlag does not need to be an integer, a __bit will do and the generated code is smaller.
You can use #define Reload_Value 625 instead of storing it. That makes smaller code too.

In init:
Clear CCP1IF instead of TMR1IF. That's the one you're using.
Make GIE = 1 the LAST thing you do after all other initialization is done.

Hope you're having fun.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
A couple of things:

If you use CCP mode 0xB (special event trigger), the Reload_Value should be 624 to account for how the CCP special event trigger works. The average cycle count shown in #19 is one TMR1 count too long.
I am surprised that the cycle count varies at all. I don't know if that is an artifact of the simulator or if it is accurately showing some 'feature' of the chip. It simulates the same here on MPLABX 5.40 with your code.
I DID change the code to use @MrChips ' method of CCP mode 0x08 and manually advancing the CCP compare register. It simulated with the exact counts expected so in the absence of testing on actual hardware, I'd use that method instead of the special event trigger. In the interrupt code just add the line:
CCPR1 += Reload_Value; // advance CCP count by 1ms
You can also use the same construct for initializing instead of calculating the individual bytes.

Nits:
timeFlag does not need to be an integer, a __bit will do and the generated code is smaller.
You can use #define Reload_Value 625 instead of storing it. That makes smaller code too.

In init:
Clear CCP1IF instead of TMR1IF. That's the one you're using.
Make GIE = 1 the LAST thing you do after all other initialization is done.

Hope you're having fun.
Here's the updated code with the changes you've suggested:
C:
#include <xc.h>
#include "config.h"

// Calculate Reload_Value for 1ms with a 20 MHz oscillator and prescaler 8
#define Reload_Value 625

volatile __bit timeFlag = 0;
volatile unsigned char seconds = 0;
volatile unsigned char minutes = 0;
volatile unsigned char hours = 0;
volatile unsigned char days = 1;
volatile unsigned char months = 1;
volatile unsigned int years = 2023;

void initializeTimer1() {
    // Configure Timer1 in 8-bit mode with a prescaler of 8
    T1CON = 0b00110000;
    
    // Configure CCP module in Special Event Trigger mode
    CCP1CON = 0b00001011; // 0x0B

    // Load the high and low bytes of Reload_Value into CCPR1
    CCPR1H = (Reload_Value >> 8); // Load high byte of Reload_Value
    CCPR1L = (Reload_Value & 0xFF); // Load low byte of Reload_Value

    // Clear Timer1 registers
    TMR1H = 0;
    TMR1L = 0;

    // Clear Timer1 interrupt flag
    TMR1IF = 0;

    // Enable Timer1 and CCP module
    TMR1ON = 1;
    CCP1IE = 1; // Enable CCP1 interrupt
}

void main() {
    // Initialize Timer1
    initializeTimer1();

    // Initialize INTCON register
    INTCON = 0; // Clear INTCON register

    // Enable global and peripheral interrupts
    INTCONbits.GIE = 1;  // Global Interrupt Enable
    INTCONbits.PEIE = 1; // Peripheral Interrupt Enable

    while (1) {

        // Check if the timeFlag is set (1ms interval)
        if (timeFlag) {
            // Increment seconds
            seconds++;

            // Handle rollover for seconds
            if (seconds >= 60) {
                seconds = 0;  // Reset seconds to 0 when it reaches 60
                minutes++;    // Increment the minutes part of the time
            }

            // Handle rollover for minutes
            if (minutes >= 60) {
                minutes = 0;  // Reset minutes to 0 when it reaches 60
                hours++;      // Increment the hours part of the time
            }

            // Handle rollover for hours
            if (hours >= 24) {
                hours = 0;  // Reset hours to 0 when it reaches 24
                days++;     // Increment the days part of the time
            }

            // Check for month and year changes (simplified, not accounting for leap years)
            if (days > 30) {  // If 30 days have passed (1 month, simplified)
                days = 1;     // Reset days to 1 to start a new month
                months++;     // Increment the months part of the time
            }

            if (months > 12) {  // If 12 months have passed (1 year, simplified)
                months = 1;  // Reset months to 1 to start a new year
                years++;     // Increment the years part of the time
            }

            // Reset the timeFlag to indicate that the 1ms interval has been processed
            timeFlag = 0;
        }
    }
}

void __interrupt() ISR() {
    if (CCP1IF) {
        // CCP1 interrupt occurred (1ms interval)
        timeFlag = 1;    // Set the timeFlag

        // Advance CCP1 compare register by Reload_Value
        CCPR1 += Reload_Value;

        // Clear the CCP1 interrupt flag
        CCP1IF = 0;
    }
}
Could you please share code you've tested on a simulator, along with an stopwatch output screenshot? Your assistance would be valuable to me, and I greatly appreciate your help.
 

ericgibbs

Joined Jan 29, 2010
21,439
Hi K,
This is an example, written in Arduino IDE, it may help.
E
Also a listing showing the Leap year change

C-like:
// Calendar  09/09/23

int Mntharray[13] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int Indx = 0;
int Year = 2023;
int Days = 0;
int Leap = 0;

void setup() {
  Serial.begin(9600);
  Serial.print("January");
  Serial.print(",");
  Serial.println(Year);
}

void loop() {
  Days = (Mntharray[Indx]);
  Leap= (Year % 4);
  if (Leap == 0) {
    (Mntharray[1]) = 29;
  } else {
    (Mntharray[1]) = 28;
  }
  Serial.print("Days=");
  Serial.println(Days);
  //Serial.print(",");
  Indx++;

  if (Indx >= 12) {
    Indx = 0;
    Serial.println(" ");
    Serial.print("January");
    Serial.print(",");
    Year++;
    Serial.println(Year);
  }
  delay(1000);
}
 

Attachments

JohnInTX

Joined Jun 26, 2012
4,787
Could you please share code you've tested on a simulator, along with an stopwatch output screenshot?
Sure. The only things I messed with are the TIMER1 and COMPARE stuff. Use in your ongoing code as desired..

CCP / TIMER 1` 1ms:
// THESE REPLACE config.h in Kittu's code - for simulation only

// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = OFF      // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = HIGH   // SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)

// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power Up Timer (Disabled)
#pragma config BOREN = SBORDIS  // Brown Out Detect (Enabled in hardware, SBOREN disabled)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576  // Watchdog Postscaler (1:1048576)

// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RE3 Disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size)

// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-01FFF (Disabled)
#pragma config CP1 = OFF        // Code Protect 02000-03FFF (Disabled)
#pragma config CP2 = OFF        // Code Protect 04000-05FFF (Disabled)
#pragma config CP3 = OFF        // Code Protect 06000-07FFF (Disabled)

// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled)
#pragma config CPD = OFF        // Data EE Read Protect (Disabled)

// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-01FFF (Disabled)
#pragma config WRT1 = OFF       // Table Write Protect 02000-03FFF (Disabled)
#pragma config WRT2 = OFF       // Table Write Protect 04000-05FFF (Disabled)
#pragma config WRT3 = OFF       // Table Write Protect 06000-07FFF (Disabled)

// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled)
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-01FFF (Disabled)
#pragma config EBTR1 = OFF      // Table Read Protect 02000-03FFF (Disabled)
#pragma config EBTR2 = OFF      // Table Read Protect 04000-05FFF (Disabled)
#pragma config EBTR3 = OFF      // Table Read Protect 06000-07FFF (Disabled)

// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

__bit timeFlag = 0;
//volatile int timeFlag = 0;
volatile unsigned char seconds = 0;
volatile unsigned char minutes = 0;
volatile unsigned char hours = 0;
volatile unsigned char days = 1;
volatile unsigned char months = 1;
volatile unsigned int years = 2023;

    // Calculate Reload_Value for 1ms with a 20 MHz oscillator and prescaler 8
#define Reload_Value 625 // (20,000,000 XTAL / 4 / 8 prescale) = 625

void initializeTimer1() {
    // Configure Timer1 in 8-bit mode with a prescaler of 8
    T1CON = 0b00110000; // mode 0x08 interrupt, CCP1 pin hi on ==

    // Configure CCP module
    // CCP1CON = 0b00001011; // 0x0B
    CCP1CON = 0b00001000; // 0x08
   
    // Load the high and low bytes of Reload_Value into CCPR1
    CCPR1 = Reload_Value;
   // CCPR1H = (Reload_Value >> 8); // Load high byte of Reload_Value
   // CCPR1L = (Reload_Value & 0xFF); // Load low byte of Reload_Value

    // Clear Timer1 registers
    TMR1H = 0;
    TMR1L = 0;

    // Clear Timer1 interrupt flag
  //  TMR1IF = 0;
    // Clear CCP1 interrupt flag
    CCP1IF = 0;
   
    // Start Timer1 and CCP module
    TMR1ON = 1;
    CCP1IE = 1; // Enable CCP1 interrupt
}

void main() {
    // Initialize Timer1
    initializeTimer1();

    // Initialize INTCON register
    INTCON = 0; // Clear INTCON register
   
    // Enable global and peripheral interrupts
    INTCONbits.PEIE = 1; // Peripheral Interrupt Enable
    INTCONbits.GIE = 1;  // Global Interrupt Enable

    while (1) {
        // Check if the timeFlag is set (1ms interval)
        if (timeFlag) {
            // Increment seconds
            seconds++;

            // Handle rollover for seconds
            if (seconds >= 60) {
                seconds = 0;  // Reset seconds to 0 when it reaches 60
                minutes++;    // Increment the minutes part of the time
            }

            // Handle rollover for minutes
            if (minutes >= 60) {
                minutes = 0;  // Reset minutes to 0 when it reaches 60
                hours++;      // Increment the hours part of the time
            }

            // Handle rollover for hours
            if (hours >= 24) {
                hours = 0;  // Reset hours to 0 when it reaches 24
                days++;     // Increment the days part of the time
            }

            // Check for month and year changes (simplified, not accounting for leap years)
            if (days > 30) {  // If 30 days have passed (1 month, simplified)
                days = 1;     // Reset days to 1 to start a new month
                months++;     // Increment the months part of the time
            }

            if (months > 12) {  // If 12 months have passed (1 year, simplified)
                months = 1;  // Reset months to 1 to start a new year
                years++;     // Increment the years part of the time
            }

            // Reset the timeFlag to indicate that the 1ms interval has been processed
            timeFlag = 0;
        }
    }
}

void __interrupt() ISR() {
    if (CCP1IF){      
               // Clear the CCP1 interrupt flag
        CCP1IF = 0;
                // advance COMPARE value
        CCPR1 += Reload_Value;
       
        timeFlag = 1;    // Notify main routine
    }
}
Kittu.jpg
 

MrChips

Joined Oct 2, 2009
34,809
The criteria for determining leap years change every 100 years and again every 400 years. This is the code I use.

C:
short IsLeapYear(short thisyear)
// is thisyear a leap year?
{
  short result;
  result = FALSE;
  if ( (thisyear % 1000) == 0 )
  { // millenium
    result = ((thisyear / 1000) % 2) == 0;
  } // millenium
  else
  { // not millenium
    if ( (thisyear % 400) == 0)
    { // every 400 years
      result = TRUE;
    } // every 400 years
    else
    { // not 400 years
      if ( (thisyear % 100) == 0)
      { // every 100 years
        result = FALSE;
      } // every 100 years
      else
      { // not 100 years
        if ( (thisyear % 4) == 0)
        { // every 4 years
          result = TRUE;
        } // every 4 years
      } // not 100 years
    } // not 400 years
  } // not millenium
  return result;
}
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
Sure. The only things I messed with are the TIMER1 and COMPARE stuff. Use in your ongoing code as desired..
Thank you very much for posting code along with an output screenshot for clarification.

If we are interested in using the internal oscillator instead of an external oscillator in a PIC microcontroller, do we need to change configuration settings only, or should we configure specific oscillator registers? Please tell me the steps involved in making this switch and ensuring proper clock operation. Additionally, In case of using the 8MHz internal oscillator, I think the instruction frequency would be 2MHz for simulating purposes
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
8MHz oscillator gives 2MHz (500ns) instruction cycle, correct.

The internal oscillator is not accurate enough to make a practical time of day clock.
When internal oscillator is used, it defaults to 8MHz but can be changed by configuring OSCCON, OSCCON2 and OSCTUNE registers in your code. See Chapter 3 of the datasheet.

The basic oscillator type is set by the CONFIGURATION bits using Window->Target Memory Views -> Configuration Bits. Click on the OPTION fields for your choices. When done click Generate Source Code to Output and copy - paste the #pragmas to the top of your code.

Figure out how accurate you want your clock to be i.e. +/- 1 second per month or per year, whatever, then do the math to see what accuracy is required of your oscillator. Then implement that.

For experimenting without regard for long term accuracy, any oscillator will do.
 
Top