12.4.7.3.1 Software Assisted Frequency Measurement
By allowing the CPU access to the accumulated results, firmware can convert the measured counts into frequencies based on existing knowledge of the reference clock frequency or period. The captured count’s corresponding register, CMxBUF, is therefore memory-mapped in this peripheral. Figure 12-14 shows the basic block diagram of this mode of operation.
Clocking Configurations
Reference Clock ≥ Time Window Generator
Monitored Clock ≥ Counter
If the reference clock is Clock Generator 6 (FRC 8 MHz), the monitor clock is Clock Generator 5 (EC 8 MHz).
Accumulation time = 0x8000 cycles of the reference clock.
The monitor clock is divided by 2, making it 4 MHz.
Time window = 0x8000/8M = 4 ms.
So, for 4ms with 4MHz clock speed, what is the expected accumulation?
0.004096 * 4M = 0x4000
The CMxBUF is expected to hold the value 0x4000 at every time window interval.
If the reference clock is Clock Generator 6 (FRC 8 MHz) and the monitor clock is Clock Generator 5 (EC 8 MHz):
Accumulation Time = 0x8000 cycles of the reference clock.
The monitor clock is divided by 2; making it 4 MHz.
Time window = 0x8000/8M = 4ms
So, for 4ms with a 4MHz clock speed, what is the expected accumulation?
0.004096 * 4M = 0x4000
The CMxBUF is expected to hold the value 0x4000 at every time window interval.
Frequency Measurement Function
//Configure clock generators before enabling monitoring
IFS0bits.C2FAILIF = 0; // enable clock Monitor2 failure interrupt
IEC0bits.C2FAILIE = 1;
IFS0bits.C2MONIF = 0; // enable clock saturation failure interrupt
IEC0bits.C2MONIE = 1;
IFS0bits.C2WARMIF = 0; // enable clock Warning failure interrupt
IEC0bits.C2WARMIE = 1;
IFS0bits.C2RDYIF = 0; // enable clock ready failure interrupt
IEC0bits.C2RDYIE = 1;
CM2CONbits.ON = 0; // disable clock monitor
//Select monitor clock source
CM2SELbits.CNTSEL = 4; //Monitoring clock clock-gen-5
//[0] = clkgen_clk[1] = System clocks
//[1] = clkgen_clk[2]
//...
//[10] = clkgen_clk[11]
//[11] = pll_fout_clk[1]
//[12] = pll_vcodiv_clk[1]
//[13] = pll_fout_clk[2]
//[14] = pll_vcodiv_clk[2]
//[15] = 1?b0 (reserved)
//[16] = ICSP clock (PGC)
//[17] = FRC - Internal 8 MHz RC oscillator
//[18] = BFRC - Internal Backup 8 MHz RC oscillator
//[19] = POSC - Primary crystal oscillator (4-32 MHz)
//[25] = REFI1 - user definable clock source
//[26] = REFI2 - user definable clock source
//Select reference clock source
CM2SELbits.WINSEL = 5; //reference clock clock-gen-6
//[0] = clkgen_clk[1] = System clocks
//[1] = clkgen_clk[2]
//...
//[10] = clkgen_clk[11]
//[11] = pll_fout_clk[1]
//[12] = pll_vcodiv_clk[1]
//[13] = pll_fout_clk[2]
//[14] = pll_vcodiv_clk[2]
//[15] = 1?b0 (reserved)
//[16] = ICSP clock (PGC)
//[17] = FRC - Internal 8 MHz RC oscillator
//[18] = BFRC - Internal Backup 8 MHz RC oscillator
//[19] = POSC - Primary crystal oscillator (4-32 MHz)
//[25] = REFI1 - user definable clock source
//[26] = REFI2 - user definable clock source
//Counter Divider Selection
CM2CONbits.CNTDIV = 1;
// 10 = Divide-by 4
// 01 = Divide-by 2
// 00 = Divide-by 1
CM2WINPR = 0x8000; //monitor clock pre scale
//Accumulation Time (in cycles) = WINPR[31:0] + 1
CM2HFAIL = 0x4500; //CLOCK MONITOR HIGH THRESHOLD FAILING
CM2LFAIL = 0x3500; //CLOCK MONITOR LOW THRESHOLD FAILING
CM2HWARN = 0x4100; //CLOCK MONITOR HIGH THRESHOLD WARNING
CM2LWARN = 0x3600; //CLOCK MONITOR LOW THRESHOLD WARNING
CM2SAT = 0x5000; //CLOCK MONITOR COUNTER SATURATION
CM2CONbits.WIDTH = 0; // 0 - Frequency Measurement
// 1 - Pulse Width and Duty Cycle Measurement
CM2CONbits.ON = 1; //enable clock monitor
while (CM2CONbits.ON);
