Unable to get PWM signals on dsPIC33fj16gs502

Thread Starter

darkfeffy

Joined Apr 1, 2009
12
Hi everyone.
I have been trying to get a 172kHz PWM signal out of the PWM1H pin of the dsPIC33fj16gs502. Here below is the code I have used. I have configured the pin accordingly, but on enabling the PWM output (PTCONbits.PTEN = 1), I get no signals on the scope. I subsequently tried using the pin as an ordinary digital output pin (code not shown), and I can output highs and lows as much as I want. So the ordinary digital output mode works. Can someone please tell me what is wrong with my code in getting the PWM module to work? I have used a debugger and I can see that all instructions execute just fine. What am I missing here? Thanks.

Rich (BB code):
#include <p33FJ16GS502.h>
 //Select internal FRC at POR
 _FOSCSEL(FNOSC_FRC);
 //Enable clock switching
 _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF);    //Clock switching mode enabled and fail safe clock monitor disabled & OSCO is general purpose IO pin
 _FWDT(FWDTEN_OFF); //Watchdog timer disabled
 _FPOR(FPWRT_PWR128); //Power-on reset timer is set to 128ms
 _FICD(ICS_PGD2 & JTAGEN_OFF); //Use PGD2 and PGC2 for ICS & JTAG disabled
 //Main function
 int main(void)
 {
 //Tune FRC frequency to 7.48MHz, i.e. 7.37*(1 + 0.00375*4)
 OSCTUNbits.TUN = 4;
 //Configure PLL divisor (M), PLL prescaler (N1) and PLL postscaler (N2) respectively
 PLLFBDbits.PLLDIV = 212;                            // M = PLLDIV + 2 = 214
 CLKDIVbits.PLLPRE = 8;                   // N1 = PLLPRE + 2 = 10 
 CLKDIVbits.PLLPOST = 0;                  // N2 = 2(PLLPOST + 1) = 2
     // Change oscillator to (FRC+PLL)
     __builtin_write_OSCCONH(0b001);                    // New Oscillator FRC with PLL
     __builtin_write_OSCCONL(0b00000001);       // Enable Clock Switch 
     while(OSCCONbits.COSC != 0b001);           // Wait for new Oscillator to become FRC with PLL    
 while(OSCCONbits.LOCK != 1);                   // Wait for Pll to Lock
 /* This part configures the auxiliary clock to be used by the PWM and ADC modules*/
 //now configuring auxilliary clock for PWM and ADC modules
 //Auxiliary clock = (selected_oscillator)*16/APSTSCLR = 120MHz
 ACLKCONbits.FRCSEL = 1; //FRC is input to auxiliary PLL
 ACLKCONbits.SELACLK = 1; //Auxiliary oscillator provides the clock source
 ACLKCONbits.APSTSCLR = 7; //Divide Auxiliary clock by 1
 ACLKCONbits.ENAPLL = 1; //Enable auxiliary PLL
 while(ACLKCONbits.APLLCK !=1); //wait for auxiliary PLL to lock
 /*This part initialises the PWM modules*/
 PTCONbits.PTSIDL = 0; //PWM time base runs in cpu idle mode
 PTCONbits.EIPU = 1; //Active period register is updated immediately (requirement from Errata)
 PTCON2bits.PCLKDIV = 0b000; //Divide by 1. Maximum PWM timing resolution is therefore 1.04ns
 PTPER = 5674; //Master time base frequency is desired to be 172kHz
 //PWM module 1&2 initializations.
 //PWM module 1 is used for flyback 1. PWM1_high for main switch and PWM1_low for complementary switch
 //MDC = 0; //Initial duty cycle in Master duty cycle register is 0;
 PWMCON1bits.FLTSTAT = 0; //Clear fault interrupt status
 PWMCON2bits.FLTSTAT = 0;
 PWMCON1bits.TRGSTAT = 0; //No trigger interrupt pending
 PWMCON2bits.TRGSTAT = 0;
 PWMCON1bits.FLTIEN = 0; //Enable Fault interrupt ***Change to 1***
 PWMCON2bits.FLTIEN = 0;
 PWMCON1bits.CLIEN = 0; //Current limit interrupt disabled because we are not interested in current-limiting function at this point
 PWMCON2bits.CLIEN = 0; 
 PWMCON1bits.TRGIEN = 0; //Trigger interrupt disabledChange to 1***
 PWMCON2bits.TRGIEN = 0; //PWM1 only is sufficient for generating the interrupt to the ADC.
 PWMCON1bits.ITB = 0; //PTPER register provides timing for the 1st and 2nd PWM generators
 PWMCON2bits.ITB = 0;
 PWMCON1bits.MDCS = 0; //PDC1 and SDC1 registers provide the duty cycle information for this PWM generator.
 PWMCON2bits.MDCS = 0; //PDC2 and SDC2 registers provide the duty cycle information for this PWM generator.
 PWMCON1bits.DTC = 0b00; //Positive dead time actively applied for all output modes
 PWMCON2bits.DTC = 0b00;
 PWMCON1bits.CAM = 0; //Enable edge-aligned mode for PWM 1
 PWMCON2bits.CAM = 0; //Enable edge-aligned mode for PWM 2
 PWMCON1bits.XPRES = 0; //External pins do not affect PWM time base
 PWMCON2bits.XPRES = 0;
 PWMCON1bits.IUE = 1; //Immediate updates to MDC/PDCx/SDCx registers
 PWMCON2bits.IUE = 1;
 PDC1 = 2837; //PWM1 generator duty cycle is initialized to 50%;
 PDC2 = 2837; //PWM2 generator duty cycle is initialized to 50%;
 //SDCx (for PWM1Low and PWM2Low) are not concerned here because in complementary mode, SDCx is not used
 PHASE2 = 2837; //Phase shift of half a period (i.e. 2.91us)
 DTR1 = 0; //High-side dead time. For now, let dead time be 0. We shall fine-tune this value later
 DTR2 = 0;
 ALTDTR1 = 0; //Low-side dead time. For now, let this be 0.
 ALTDTR2 = 0;
 TRGCON1bits.TRGDIV = 1; //Trigger PWM1 output for every 2nd trigger event.
 //Is it necessary to trigger PWM2 output as well?
 TRGCON1bits.TRGSTRT = 0; //Wait 0 PWM cycles before generating the first trigger event after PWM is enabled.
 TRGCON1bits.DTM = 0; //Datasheet says secondary trigger event will not be combined will not be combined to create PWM trigger. Not so sure here????
 IOCON1bits.PENH = 1; //PWM module controls PWM1High pin
 IOCON2bits.PENH = 1; //PWM module controls PWM2High pin
 IOCON1bits.PENL = 1; //PWM module controls PWM1Low pin
 IOCON2bits.PENL = 1;
 IOCON1bits.POLH = 0; //PWMxH is active high
 IOCON2bits.POLH = 0;
 IOCON1bits.PMOD = 0b00; //PWM I/O pin is in the complementary output mode
 IOCON2bits.PMOD = 0b00;
 //De-comment this section to improve safety. Don't forget to disable over-ride in code, in order to turn-on PWM
 /*     IOCON1bits.OVRDAT = 0; //Over-ride data on PWM output pin. In this case, output is off when overriden. At start-up, PWM will be off.
 IOCON2bits.OVRDAT = 0;
 IOCON3bits.OVRDAT = 0;
 IOCON1bits.OVRENH = 1; //Enable over-ride (at start-up. Need to disable in order to run PWM
 IOCON1bits.OVRENL = 1;
 IOCON2bits.OVRENH = 1;
 IOCON2bits.OVRENL = 1;
 IOCON3bits.OVRENH = 1;
 IOCON3bits.OVRENL = 1;
 */
 TRIG1bits.TRGCMP = 0; //Trigger ADC module immediately PWM starts without any delay. ***This value might need to be fine-tuned***
 /*This sub-section configures the PWM pins as digital outputs*/
 TRISAbits.TRISA3 = 0;  //PWM1L
 TRISAbits.TRISA4 = 0;  //PWM1H
 TRISBbits.TRISB14 = 0; //PWM2L
 TRISBbits.TRISB13 = 0; //PWM2H
 /*End of sub-section*/
 //Now we activate the PWM module
 PTCONbits.PTEN = 1; //PWM activated
 while(1)
 {
 Nop();
 Nop();
 Nop();
 }
 }
 

ErnieM

Joined Apr 24, 2011
8,377

Thread Starter

darkfeffy

Joined Apr 1, 2009
12
Sorry I don't have anything specific to say. I skipped over these devices and jumped from 8 to 32 bit cores and thus have zero experience with them.

The PWM should appear in the MPLAB simulator which may be faster then checking the actual hardware with an oscope.

The PWM has it's own (huge) section: http://ww1.microchip.com/downloads/en/DeviceDoc/70323D.pdf

And you may get a better faster answer if you ask on the microchip forums: http://www.microchip.com/forums/f178.aspx
Thanks for the reply. Turns out that I am having some shaky contacts on my circuit. One second u get a signal , the next second it goes off. I am working to isolate all such contacts. Thanks again.
By the way, how do you observe signals on the MPLAB simulator?
 

ErnieM

Joined Apr 24, 2011
8,377
By the way, how do you observe signals on the MPLAB simulator?
There's a few ways, my preference is to open the watch window (under the View menu) and select which registers or variables I want to see.

Somewhere there's a setting that when enabled will show a variable or register in a tooltip when you mouse over the iten in a paused program.
 
Top