If you have a MCU with a fixed 31 kHz (LFINTOSC) I'm sure there is a way to measure the period of the current FOSC to a few percentage points using a timer with the LFINTOSC as the reference.I don't know of a MCU that can read its clock frequency - what would it use as a reference clock?
It's not going to be accurate but a LFINTOSC timer reference to a instruction speed timing loop should be able to tell if the MCU speed is half (PLL/clock setting error) what it should be easily.Except that an external crystal is going to more accurate then LFINTOSC, so I suppose you could do it the other way round and measure LFINTOSC against the crystal with some software, but it isn't built in to the micro.
Clear and use the timer1 interrupt flag (no timer 0 and 1 interrupt are not enabled) as the gate complete event. Enable the gate signal. When the timer1 interrupt flag is set (polled) the timer1 16-bit counter will have the clock frequency in 100us counts.Timer1 Gate
The Timer1 Gate feature allows the PIC® MCU device to easily time external events using T1G pin as the input or analog events using an internal Comparator. This can be useful for timing the high pulse time of a waveform. The Timer1 Gate can control when the Timer1 increments. It is essentially an on/off switch for the Timer1 counter. There are several individual bits in the Timer1 Gate Control register (T1GCON register) that control the operation of the Timer1 Gate. Each setting is covered below.
/*
* File: speed.h
* Author: root
*
* Created on April 30, 2021, 11:14 PM
*/
#ifndef SPEED_H
#define SPEED_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>
#include "mcc_generated_files/tmr0.h"
#include "mcc_generated_files/tmr1.h"
uint16_t get_fosc(void);
void init_get_fosc(void);
#ifdef __cplusplus
}
#endif
#endif /* SPEED_H */
#include "speed.h"
/*
* return controller clock speed
*/
uint16_t get_fosc(void)
{
while (!TMR1GIF); // wait unit the count gate is done. init_get_fosc must be executed first
return TMR1_ReadTimer(); // return the number of counts for the period set by timer0
}
/*
* configure timer 0 and 1 for processor timing duty
*/
void init_get_fosc(void)
{
TMR1GIF = 0; // clear gate interrupt flag
TMR1_WriteTimer(0); // zero counter date
/*
* trigger the count gate using the output of timer0 for one cycle, one shot
*/
TMR1_StartSinglePulseAcquisition(); // Starts the single pulse acquisition in TMR1 gate operation.
}
// init in the main startup section
init_get_fosc();
// in main for the display text buffer
sprintf(buffer, "%u0000Hz FOSC", get_fosc());
by Aaron Carman
by Duane Benson
by Duane Benson
by Jake Hertz