2
votes
  • I'm trying to generate a 10% duty cycle-1kHz PWM with a clock at 80Mhz (F_osc) using the inbuilt (Hardware) high speed PWM.

  • According to the documentation, Base Period (number for the PTPER) is calculated by

    PTPER = F_osc / [(F_pwm) x (PWM_Clk_Prescale)]

Substituting F_osc = 80Mhz, F_pwm = 1khz and Prescale = 8, I'm getting a count of PTPER=10,000.

However, from my output on an oscilloscope, I can see that I have PWM frequency of ~2khz.PWM output.

Am I doing anything wrong? Below is my code --

#include<p33EP512MU810.h>
#include<p33Exxxx.h>

//---------------- compiler directives------------------
_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF  & POSCMD_XT);    // Clock Switching Enabled and Fail Safe Clock Monitor is disabled
                                                    // OSC2 Pin Function: OSC2 is Clock Output
                                                    // Primary Oscillator Mode: XT Crystal
_FWDT(FWDTEN_OFF);                                  // Watchdog Timer Enabled/disabled by user software
//------------------------------------------------------


//function to initialise oscillator and set up clock
void Init_Oscillator(void)
{
   // Configure Oscillator to operate the device at 40Mhz
    // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
    // Fosc= 12M*40/(3*2)=80Mhz for 12M input clock
    // 0.5M < Fin/N1 < 8MHz
    // 100M < Fin*M/N2 < 200M
    // Fcy  = Fosc / 2 = 40 MIPS
    PLLFBD       = 38;  // M=80
    CLKDIVbits.PLLPOST = 0;   // N2=2
    CLKDIVbits.PLLPRE  = 1;   // N1=3
    OSCTUN             = 0;   // Tune FRC oscillator, if FRC is used
    RCONbits.SWDTEN=0;     // Disable Watch Dog Timer

    // Clock switch to incorporate PLL
    __builtin_write_OSCCONH(0x03);              // Initiate Clock Switch to
                                                                                            // Primary Oscillator with PLL (NOSC=0b011)
    __builtin_write_OSCCONL(0x01);              // Start clock switching
    while (OSCCONbits.COSC != 0b011);           // Wait for Clock switch (to XT w/ PLL) to occur
    while(OSCCONbits.LOCK!=1) {}; // Wait for PLL to lock
}

void Init_PWM(void)
{
    /**** PTCON: PWM Time Base Control Register ****/
    PTCONbits.PTEN   = 0;   // Timer Enable bit:    DISABLE MCPWM

        //---------------------------------------------------------------
        //Prescaler 1:8
        PTCON2bits.PCLKDIV = 0b011; // PCLKSEL: 1,2,4,8,16,32,64
        //mode selection
        PWMCON1 = 0x0000;          //PTPER holds period count of PWM
        //Independent mode enable
        IOCON1 = 0xCC00; //fig 14-35 of PWM manual
        // 0xCC00 => PENH high, PENL high, PMOD: 11- True Independent PWM o/p

        //---------------------------------------------------------------
        /**** PTPER: PWM Time Base Period Register ****/
    PTPER = 10000; // Period Value bits
        //Enable PWM timer
        PTCONbits.PTEN   = 1;   // Timer Enable bit:    ENABLE MCPWM
}
//--- extra settings:
// 1) Stop in IDLE MODE :: PTCONbits.PTSIDL = 1 (yes)
// 2) Setting a particular pin as output ==> IOCONxbits.PENH(/L) = 1(enabled)
// 3) MDC,PDC,SDC et al depend on the PWM MODE.
//    Resp, selection of PTPER,PHASE,SPHASE.
//---


int main(void)
{
        Init_Oscillator();
    Init_PWM();// Initialize PWM module
        PDC1 = 1000; // This sets the duty cycle.
    while(1); //loop forever //while

return 0;
}
2

2 Answers

3
votes

Despite your comments, I believe you have

PLLDIV = 78 // M = 80

So,

FOSC = FIN * PLLDIV / ((PLLPRE + 2) * 2 * (PLLPOST + 1))

FOSC = 8MHz * 80 / ((1 + 2) * 2 * (0 + 1))

FOSC = 8MHz * 80 / 6

FOSC = ~ 107 MHz
0
votes

your pwm CONFIG for 80MHZ is right but make sure that your input frequency is 12MHZ ...i already test pwm for 80mhz with the same config of PWM and its generating proper output as you need 1KHZ. so check your PLL and Fcrystal config. i think you are generating pll 160MHZ.if you are using M=80 then you have to replace it with M=40 (PLLFBD = 38;),correct your comment or code.