The PIC microcontroller contains a module known as the Output Compare module which is used to generate Pulse Width Modulation signals. The Output Capture or OC module generates pulses using the timer and outputs those pulses on the microcontroller pin. The most common use of the Output Compare module is to generate PWM signals which we will explore in the post.

Understanding Output Compare

As previously mentioned the Output Compare module can be used for many functions when generating pulses. One of the most important of which is generating Pulse-With Modulation or PWM signals.

The PWM signals are very important to a microcontroller. If you want to do things like controlling a motor or lights that you can dim, the PWM module is what you should be using.

What exactly is PWM? Well PWM is a name used to describe digital signals whose pulses are varied under the control of the microcontroller. By varying the HIGH and LOW time of the signal we can achieve a pulse that will appear to have a certain voltage level. The amount of time the signal is spent in the on position is called the duty cycle of the signal.

Like stated above, the output capture module that generates the PWM signal requires a timer for generating the time base, and in the case of the PIC32Mx230F054B this timer may be a 16-bit timer or a 32-bit timer that may be used for this purpose.

We will use Timer2 as our timer therefore we will be using the PWM in 16-bit mode. If you wish to use 32-bit mode you will need to configure this when you setup the timer.

The PWM on the PIC32 is very complex with the ability to operate in either 16 or 32-bit mode, has fault protection as well as the ability to generate interrupts and is very powerful. You can achieve precise waveform generation using the module. In our case though we will use the PWM module in simple operation.

It is very important when configuring the PWM module to remember to check the speed of the peripheral bus clock. In our example the PBCLK is half the frequency of the SYSCLK which is very important to determine the value of PR2 to for the frequency of the square wave you desire.


Connections

To see the waveform simply connect the probe of your oscilloscope to the PWM pin of the PIC32MX270F256D. If you do not have an oscilloscope you may connect an LED, though to see dimming you would need to increase the delay after the value is set in the OC1RS register.


C Program

/*
 * File: Main.c
 * Author: Armstrong Subero
 * Processor: PIC32MX270F256D w/Ext OSC @ 4MHz, PLL to 48 MHz, 3.3v
 * Program: 08_Output_Compare
 * Compiler: XC32 (v1.44, MPLAX X v4.00)
 * Program Version: 1.0
 *                             
 * Program Description: This Program Allows PIC32MX270F256D to generate a 10 kHz
 *                      square wave using the output capture module on channel 1
 *                      that varies from 0 to 100% duty cycle.
 *                      
 * Hardware Description: An oscilloscope probe is connected to PIN B4
 * 
 * Change History:
 *
 * Author             Rev     Date          Description
 * Armstrong Subero   1.0     03/04/2018    Initial Release.
 * 
 *                      
 * Created April 3rd, 2018, 12:05 PM
 */

/*******************************************************************************
 Includes and defines
*******************************************************************************/
#include <xc.h>
#include "PIC32MX270_STD.h"
#include "Delay.h"

#define LED LATBbits.LATB14

/*******************************************************************************
* Function Name: void initMain (void)
*
* Specification: initializes main
*
*******************************************************************************/
void initMain(void)
{  
    uc_init();                  // initialize microcontroller
   
    // unlock PPS
    systemReg_Unlock();
    CFGCONbits.IOLOCK = 0;

    RPB4Rbits.RPB4R = 0x0005;   //RB4->OC1

    // lock PPS
    CFGCONbits.IOLOCK = 1;
    systemReg_Lock();
    
    /////////////////////
    // Configure Timer2
    /////////////////////
    T2CONbits.TCKPS0 = 0;       // Timer2 Prescale 1:1
    T2CONbits.TCKPS1 = 0;
    T2CONbits.TCKPS2 = 0;
    
    // Period = (PR + 1 ) * Prescale * 41.667 (PBCLK = 24 MHz)
    // Period = 2400 * 1 * 41.667 = ~ 10 kHz 
    PR2 = 2399;
    TMR2 = 0;                  // TMR2 count = 0
    
    ////////////////////
    // Configure PWM
    ///////////////////
    OC1CONbits.OCM0 = 0;       // PWM mode, fault pin disabled
    OC1CONbits.OCM1 = 1;
    OC1CONbits.OCM2 = 1; 
    OC1CONbits.OCTSEL = 0;     // Timer2 is clock source
    OC1CONbits.OC32 = 0;       // 16-bit timer source
    OC1CONbits.SIDL =  0;      // continue operation in IDLE mode
    
    // duty cycle = OCRS/PR+1 = 50%
    OC1RS = 1200;              // secondary value  
    OC1R = 1200;               // primary value  
    
    T2CONbits.ON = 1;          // turn Timer2 on
    OC1CONbits.ON = 1;         // turn OC1 on
}


/*******************************************************************************
* Function Name: void main (void)
*
* Specification: main function
*
*******************************************************************************/
void main(void) {
    
    initMain();         // initializes main function
    
    uint16_t i;
    uint16_t value = 0;
    
    while(1)
    {
        // vary duty cycle from  0 to 100%
        for (i = 0; i <= 2400; i++)
        {
            value = i;
            OC1RS = value;
            delay_us(500);
        } 
    }
}


In the program in main we setup Timer2 to generate for 10kHz PWM operation assuming a clock speed of 24 Mhz. Output Capture module to operate in PWM mode and disable the fault feature, we use Timer2 as the clock source and operate in 16-bit mode.

In the program loop we vary the duty cycle of the signal from 0 to 100% which can be viewed on an oscilloscope. Alternatively if you increase the delay time, you will be able to observe the duty cycle on an LED.


Link to Project

You can download the entire project here!

Output Compare Project

 

Leave a Reply

Your email address will not be published. Required fields are marked *