Advertisement

If only I had one more [insert function here]!

January 30, 2018

Luciodjs-January 30, 2018

Setting the Time Base

The time base can be implemented with any standard timer as long as it can produce a periodic pulse with the desired frequency (~500 Hz in our case). For our application, the timer can be an 8-bit basic timer/counter and can be shared with other functions (PWMs or otherwise). In our application, we reused Timer2, a basic (8-bit) timer with a match register (T2PR). The configuration of the Timer2 module as the base timer requires only a pair of registers to be initialized as illustrated in Listing 1.

void TMR2_Initialize(void)
{
    // T2CKPS 1:64; T2OUTPS 1:1; TMR2ON off
    T2CON = 0x60;
    // T2CS FOSC/4
    T2CLKCON = 0x01;
    // T2 period 
    T2PR = 0xFF;
    // Clearing Interrupt flag
    PIR4bits.TMR2IF = 0;
    // Start TMR2
    T2CONbits.TMR2ON = 1;
}

Listing 1: Timer2 basic initialization 

The traditional way to develop such an initialization routine would require us to dig into the lengthy datasheet of the PIC microcontroller of choice and carefully identify the bit patterns required for each of the registers. This can be a lengthy and error-prone process, even for a simple peripheral. The better way to proceed nowadays is to use the MPLAB Code Configurator, a rapid development tool (plugin) integrated in the MPLAB X IDE that allows us to generate the same code (an initialization routine very similar to Listing 1) with only a few mouse clicks. In fact, the tool is often used to discover device features and experiment quickly with the many options offered by the Core Independent Peripherals.

In figure 2, you can see how all the options available for Timer2 are laid out for us to pick from multiple selection boxes and entry fields.

click for larger image

Figure 2 – MPLAB Code Configurator (MCC) Dialog Window for Timer 2 configuration (Source: Microchip Technology)

Configuring the Limit Counter

The limit counter is a little more sophisticated function, but not an unreasonably complex or rare one. Once triggered, this timer needs to be able to count up to a limit value (as the name implies), generate a pulse and stop. It will reset and start again only upon the next trigger input. This function is often referred to as a retriggerable monostable, or in the PIC literature it is known as a Hardware Limit Timer (HLT).

Unfortunately, if we desire a 12-bit or higher resolution on the PWM duty cycle, the typical HLT available on a PIC microcontroller is not going to cut it. On modern PIC microcontrollers, even numbered timers offer the HLT function but provide only an 8-bit counter. However, there is another less-known peripheral that can get us the resolution we crave.

click for larger image

Figure 3 – Block diagram of a Signal Measurement Timer (SMT) (Source: Microchip Technology)

This is the Signal Measurement Timer (SMT) represented in Figure 3.

If the HLT is little more than a timer with one extra trigger/reset input, the SMT is essentially a timer with two such inputs. It happens that there are a number of interesting ways to combine those two inputs to obtain a variety of time, frequency and duty cycle measurements -- hence the name.

The device datasheet lists as many as 11 such modes, which is enough to scare most novice users and make the SMT the most misunderstood and under-utilized among the CIPs. I have no room here to dive into the details of all the modes, but it will suffice to mention that one of them – perhaps misleadingly named Window Measurement Mode – essentially turns the SMT into a HLT. In fact, it’s a very large HLT, as the SMT has a 24-bit counter and a period register of matching size.

Once again, the configuration of the Signal Measurement Timer (SMT1) can be significantly simplified by using the MCC tool, as illustrated in Figure 4.

click for larger image

Figure 4 – MCC Dialog Window for the SMT1 module (Source: Microchip Technology)

With a few mouse clicks, we can automatically generate an initialization function similar to Listing 2. In fact, that is precisely how this function was generated in the first place. A few comments were streamlined later for the sake of brevity and clarity.

void SMT1_Initialize(void)
{
    // WPOL high/rising edge enabled; SMT1EN enabled; SMT1PS 1:1 Prescaler
    SMT1CON0 = 0x80;
    // SMT1MODE Windowed measure; SMT1GO disabled;
    SMT1CON1 = 0x44;
    // SMT1CSEL HFINTOSC
    SMT1CLK = 0x02;
    // SMT1WSEL TMR2_postscaled;
    SMT1WIN = 0x05;
}

Listing 2 – SMT1 module initialization function

< Previous
Page 2 of 3
Next >

Loading comments...