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

Figure 12-14. Frequency Measurement Function – CPU

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);