Real-Time Clock Project

ericgibbs

Joined Jan 29, 2010
21,439
hi K,
Which method will you be using to initialize the program with the precise current time/date, at power On and/or power resume?

E
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
hi K,
Which method will you be using to initialize the program with the precise current time/date, at power On and/or power resume?
At Power On and/or Power Resume: There are two scenarios to consider:

  • At Power On: This refers to setting the time and date when device or system is initially powered up.
  • At Power Resume: This means setting the time and date when device or system resumes operation after a temporary loss of power

I'm planning to try both methods of initializing the program with precise time and date to understand their pros and cons better. In your experience, which method would you recommend trying first, and why?
 

ericgibbs

Joined Jan 29, 2010
21,439
hi K,
As you plan to output the Time/Date of the Software clock into a PC via the UART, you could consider using the PC, UART to load the Date/Time via UART to the MCU Software clock.
Which version of the PC Serial Comms are you planning to use on the PC end?

eg: D,100923<crlf> and T,1345<crlf>

I expect at some stage you will want to add an Alarm time, say A,1234<crlf>

E
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
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.

For experimenting without regard for long term accuracy, any oscillator will do.
I'm currently trying to set up the internal 8MHz oscillator as the clock source for my microcontroller. However, I'm not very familiar with how to correctly configure the configuration bits for this oscillator. I want set 1ms timerinttrupt with CCP special event trigger

C:
#define _XTAL_FREQ 8000000

// PIC18F45K80 Configuration Bit Settings

// 'C' source line config statements

// 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 = ON       // Extended Instruction Set (Enabled)

// 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>

void main(void) {
    return;
}

I mean, which software serial program in the PC?
eg: Procomm, Termite etc ...
Mostly I use putty, Hercules, Tera Term
 

MrAl

Joined Jun 17, 2014
13,704
I'm planning to make a real-time clock project as a hobby that utilizes a 1ms timer interrupt using a PIC microcontroller. My goal is to accurately count interrupts to keep track of minutes, seconds, hours, days, months, and years.

I have attached the code I've written and a screenshot from the simulator to provide a clearer view of what I've done so far.

C:
//PIC18F45K80
#include <xc.h>
#include "config.h"

volatile int count = 0; // Declare count as a global variable

void initializeHardware() {
    // Set LATx registers to initial states (all low)
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;

    // Set TRISx registers to configure pins as outputs (all output)
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;

    // Additional configuration for unused peripherals
    ANCON0 = 0x00; // Set all analog pins to digital mode
    ANCON1 = 0x00; // Set all analog pins to digital mode
    CM1CON = 0x00; // Turn off Comparator 1
    CM2CON = 0x00; // Turn off Comparator 2
    ADCON0 = 0x00; // Disable A/D conversion
    ADCON1 = 0x00; // Disable A/D conversion
    ADCON2 = 0x00; // Disable A/D conversion
}
    // Timer0 configuration for a 1ms interrupt
void configureTimer0() {

    T0CON = 0x88; // 16-bit mode, 1:256 prescaler

    // Preload Timer0 with the values 0xEC for the high byte and 0x78 for the low byte
    TMR0H = 0xEC;
    TMR0L = 0x78;

    // Enable global interrupt (GIE = 1) and Timer0 overflow interrupt (TMR0IE = 1)
    INTCON = 0xA0;
}

void main(void) {
    initializeHardware();
    configureTimer0();

    while (1) {
        //  main code here
    }
}

void __interrupt() isr() {
    if (TMR0IF == 1) {  // Timer0 overflow interrupt flag bit
        TMR0IF = 0;     // Clear the interrupt flag
        count++;        // Increment a counter

        // Reload Timer0 with the precise preload values for a 1ms interrupt
        TMR0H = 0xEC;
        TMR0L = 0x78;
    }
}
I'm interested in measuring the interrupt latency of my PIC microcontroller in this project. Could you please guide me on how to accurately measure interrupt latency time?

Attached Files:


View attachment 302205


I'm open to any feedback or guidance you can offer. This project is all about learning and having fun with microcontrollers, so I appreciate any help you can provide. @JohnInTX

Thank you in advance for your time and expertise!
Hi,

It is very difficult to make a real time clock from scratch without any external type of synchronization. You end up with something that can be off by several minutes per month. That's even when you include code to handle a calibration phase. Even some of the oscillators that are supposed to be temperature compensated may still drift.

The best bet is to get one of those little real time clock boards with the onboard backup battery. These can keep time to seconds per year. You have to get the right model though because there are better ones and not so good ones.
I can look this up for you if you think you want to use one.

Most crystals have to be temperature compensated to get better stability. Do a little math and calculate how much the clock will be off after one year using a crystal with an accuracy of 10 parts per million.
 

cmartinez

Joined Jan 17, 2007
8,760
I'm currently trying to set up the internal 8MHz oscillator as the clock source for my microcontroller. However, I'm not very familiar with how to correctly configure the configuration bits for this oscillator. I want set 1ms timerinttrupt with CCP special event trigger

C:
#define _XTAL_FREQ 8000000

// PIC18F45K80 Configuration Bit Settings

// 'C' source line config statements

// 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 = ON       // Extended Instruction Set (Enabled)

// 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>

void main(void) {
    return;
}


Mostly I use putty, Hercules, Tera Term
Trying to use the MCU's internal oscillator as a RTC is a GRAVE mistake ... I've been there, done that, and paid the consequences.

No matter how hard you try, temperature fluctuations throughout the day will result in drift in the internal oscillator, resulting in unacceptable inaccuracies that will generate an error spanning at least a few seconds in just one day.

What I did instead was use an external 32.768 kHz crystal oscillator as the MCU's system clock. That way timekeeping remains accurate, and power draw is also minimized to the point of consuming less than 13 uA at 3.3V, making it ideal for a battery powered device.
 

John P

Joined Oct 14, 2008
2,061
My clock tells perfect time twice a day and I never have to replace the battery.
Yes, but I expect it's difficult to tell when it's showing the correct time and when it's not. It would probably be helpful to have an accurate backup clock, and when it matched yours, you'd know that the time was correct.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
I believe you may have missed my post #6, where I mentioned my intention to explore and enhance my coding skills further. I understand that using RTC hardware would be the best solution for precise timekeeping, I'm interested in learning through coding.
 

cmartinez

Joined Jan 17, 2007
8,760
I believe you may have missed my post #6, where I mentioned my intention to explore and enhance my coding skills further. I understand that using RTC hardware would be the best solution for precise timekeeping, I'm interested in learning through coding.
Trust me, if you use my technique, you'll have plenty of coding to work thorough to get the results that you want.
 

MrAl

Joined Jun 17, 2014
13,704
I believe you may have missed my post #6, where I mentioned my intention to explore and enhance my coding skills further. I understand that using RTC hardware would be the best solution for precise timekeeping, I'm interested in learning through coding.
Hi,

Yes it is interesting to write some code to keep time. It takes a bit of doing and it's hard to get really accurate, but still interesting and you can discover what makes it so hard to do and if it is even possible to get a seconds per year accuracy.

As someone mentioned though, if you sync to the line voltage (at least in the US) you can get decent timing accuracy because they keep the line frequency updated. I don't know if they still do it this way, but they used to adjust it to keep the average frequency constant like at 60Hz. That means if it went up to 60.1Hz for a while they would adjust it to 59.9Hz for a while to compensate. The average would then be 60Hz to whatever accuracy they used. It kept many clocks accurate for years.
This is still interesting to code, and you have to find a way to detect the line frequency without connecting directly to the line voltage so there is a little hardware lesson to be had there as well. An opto coupler is one choice.
 

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..
I've recently noticed that I no longer see the time value in the stopwatch window, whereas I used to see it before. Could you @JohnInTX please help me understand why this might be happening and how I can get the time value back in the stopwatch window?

MPLAB V6.05

1694609120076.png
 

JohnInTX

Joined Jun 26, 2012
4,787
I've recently noticed that I no longer see the time value in the stopwatch window, whereas I used to see it before. Could you @JohnInTX please help me understand why this might be happening and how I can get the time value back in the stopwatch window?

MPLAB V6.05

View attachment 302703
If you are using the simulator, I don’t know why the stopwatch does not work. What changed in your environment?
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
If you are using the simulator, I don’t know why the stopwatch does not work. What changed in your environment?
I made a few changes to my projects, such as setting the instructions frequency to 2MHz and enabling window features like the logic analyzer I/O pin. However, I'm encountering an issue where I can't seem to create MCC project with this IDE.
 

JohnInTX

Joined Jun 26, 2012
4,787
Sorry but I don’t know. I don’t use MCC or the late versions of MPLABX. Maybe someone else knows. Be sure to read the release notes for the versions of MPLABX and MCC especially for Known Issues
 

Thread Starter

Kittu20

Joined Oct 12, 2022
511
Sorry but I don’t know. I don’t use MCC or the late versions of MPLABX. Maybe someone else knows. Be sure to read the release notes for the versions of MPLABX and MCC especially for Known Issues
I wanted to mention that I updated my IDE and compiler versions. I am using older version, and this update solved the issue I had with not getting timing values on my stopwatch.
 
Top