Unable to get PWM signals on dsPIC33fj16gs502

Discussion in 'Embedded Systems and Microcontrollers' started by darkfeffy, May 31, 2012.

  1. darkfeffy

    Thread Starter Member

    Apr 1, 2009
    12
    2
    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.

    Code ( (Unknown Language)):
    1.  
    2. #include <p33FJ16GS502.h>
    3.  //Select internal FRC at POR
    4.  _FOSCSEL(FNOSC_FRC);
    5.  //Enable clock switching
    6.  _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF);    //Clock switching mode enabled and fail safe clock monitor disabled & OSCO is general purpose IO pin
    7.  _FWDT(FWDTEN_OFF); //Watchdog timer disabled
    8.  _FPOR(FPWRT_PWR128); //Power-on reset timer is set to 128ms
    9.  _FICD(ICS_PGD2 & JTAGEN_OFF); //Use PGD2 and PGC2 for ICS & JTAG disabled
    10.  //Main function
    11.  int main(void)
    12.  {
    13.  //Tune FRC frequency to 7.48MHz, i.e. 7.37*(1 + 0.00375*4)
    14.  OSCTUNbits.TUN = 4;
    15.  //Configure PLL divisor (M), PLL prescaler (N1) and PLL postscaler (N2) respectively
    16.  PLLFBDbits.PLLDIV = 212;                            // M = PLLDIV + 2 = 214
    17.  CLKDIVbits.PLLPRE = 8;                   // N1 = PLLPRE + 2 = 10
    18.  CLKDIVbits.PLLPOST = 0;                  // N2 = 2(PLLPOST + 1) = 2
    19.      // Change oscillator to (FRC+PLL)
    20.      __builtin_write_OSCCONH(0b001);                    // New Oscillator FRC with PLL
    21.      __builtin_write_OSCCONL(0b00000001);       // Enable Clock Switch
    22.      while(OSCCONbits.COSC != 0b001);           // Wait for new Oscillator to become FRC with PLL    
    23.  while(OSCCONbits.LOCK != 1);                   // Wait for Pll to Lock
    24.  /* This part configures the auxiliary clock to be used by the PWM and ADC modules*/
    25.  //now configuring auxilliary clock for PWM and ADC modules
    26.  //Auxiliary clock = (selected_oscillator)*16/APSTSCLR = 120MHz
    27.  ACLKCONbits.FRCSEL = 1; //FRC is input to auxiliary PLL
    28.  ACLKCONbits.SELACLK = 1; //Auxiliary oscillator provides the clock source
    29.  ACLKCONbits.APSTSCLR = 7; //Divide Auxiliary clock by 1
    30.  ACLKCONbits.ENAPLL = 1; //Enable auxiliary PLL
    31.  while(ACLKCONbits.APLLCK !=1); //wait for auxiliary PLL to lock
    32.  /*This part initialises the PWM modules*/
    33.  PTCONbits.PTSIDL = 0; //PWM time base runs in cpu idle mode
    34.  PTCONbits.EIPU = 1; //Active period register is updated immediately (requirement from Errata)
    35.  PTCON2bits.PCLKDIV = 0b000; //Divide by 1. Maximum PWM timing resolution is therefore 1.04ns
    36.  PTPER = 5674; //Master time base frequency is desired to be 172kHz
    37.  //PWM module 1&2 initializations.
    38.  //PWM module 1 is used for flyback 1. PWM1_high for main switch and PWM1_low for complementary switch
    39.  //MDC = 0; //Initial duty cycle in Master duty cycle register is 0;
    40.  PWMCON1bits.FLTSTAT = 0; //Clear fault interrupt status
    41.  PWMCON2bits.FLTSTAT = 0;
    42.  PWMCON1bits.TRGSTAT = 0; //No trigger interrupt pending
    43.  PWMCON2bits.TRGSTAT = 0;
    44.  PWMCON1bits.FLTIEN = 0; //Enable Fault interrupt ***Change to 1***
    45.  PWMCON2bits.FLTIEN = 0;
    46.  PWMCON1bits.CLIEN = 0; //Current limit interrupt disabled because we are not interested in current-limiting function at this point
    47.  PWMCON2bits.CLIEN = 0;
    48.  PWMCON1bits.TRGIEN = 0; //Trigger interrupt disabledChange to 1***
    49.  PWMCON2bits.TRGIEN = 0; //PWM1 only is sufficient for generating the interrupt to the ADC.
    50.  PWMCON1bits.ITB = 0; //PTPER register provides timing for the 1st and 2nd PWM generators
    51.  PWMCON2bits.ITB = 0;
    52.  PWMCON1bits.MDCS = 0; //PDC1 and SDC1 registers provide the duty cycle information for this PWM generator.
    53.  PWMCON2bits.MDCS = 0; //PDC2 and SDC2 registers provide the duty cycle information for this PWM generator.
    54.  PWMCON1bits.DTC = 0b00; //Positive dead time actively applied for all output modes
    55.  PWMCON2bits.DTC = 0b00;
    56.  PWMCON1bits.CAM = 0; //Enable edge-aligned mode for PWM 1
    57.  PWMCON2bits.CAM = 0; //Enable edge-aligned mode for PWM 2
    58.  PWMCON1bits.XPRES = 0; //External pins do not affect PWM time base
    59.  PWMCON2bits.XPRES = 0;
    60.  PWMCON1bits.IUE = 1; //Immediate updates to MDC/PDCx/SDCx registers
    61.  PWMCON2bits.IUE = 1;
    62.  PDC1 = 2837; //PWM1 generator duty cycle is initialized to 50%;
    63.  PDC2 = 2837; //PWM2 generator duty cycle is initialized to 50%;
    64.  //SDCx (for PWM1Low and PWM2Low) are not concerned here because in complementary mode, SDCx is not used
    65.  PHASE2 = 2837; //Phase shift of half a period (i.e. 2.91us)
    66.  DTR1 = 0; //High-side dead time. For now, let dead time be 0. We shall fine-tune this value later
    67.  DTR2 = 0;
    68.  ALTDTR1 = 0; //Low-side dead time. For now, let this be 0.
    69.  ALTDTR2 = 0;
    70.  TRGCON1bits.TRGDIV = 1; //Trigger PWM1 output for every 2nd trigger event.
    71.  //Is it necessary to trigger PWM2 output as well?
    72.  TRGCON1bits.TRGSTRT = 0; //Wait 0 PWM cycles before generating the first trigger event after PWM is enabled.
    73.  TRGCON1bits.DTM = 0; //Datasheet says secondary trigger event will not be combined will not be combined to create PWM trigger. Not so sure here????
    74.  IOCON1bits.PENH = 1; //PWM module controls PWM1High pin
    75.  IOCON2bits.PENH = 1; //PWM module controls PWM2High pin
    76.  IOCON1bits.PENL = 1; //PWM module controls PWM1Low pin
    77.  IOCON2bits.PENL = 1;
    78.  IOCON1bits.POLH = 0; //PWMxH is active high
    79.  IOCON2bits.POLH = 0;
    80.  IOCON1bits.PMOD = 0b00; //PWM I/O pin is in the complementary output mode
    81.  IOCON2bits.PMOD = 0b00;
    82.  //De-comment this section to improve safety. Don't forget to disable over-ride in code, in order to turn-on PWM
    83.  /*     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.
    84.  IOCON2bits.OVRDAT = 0;
    85.  IOCON3bits.OVRDAT = 0;
    86.  IOCON1bits.OVRENH = 1; //Enable over-ride (at start-up. Need to disable in order to run PWM
    87.  IOCON1bits.OVRENL = 1;
    88.  IOCON2bits.OVRENH = 1;
    89.  IOCON2bits.OVRENL = 1;
    90.  IOCON3bits.OVRENH = 1;
    91.  IOCON3bits.OVRENL = 1;
    92.  */
    93.  TRIG1bits.TRGCMP = 0; //Trigger ADC module immediately PWM starts without any delay. ***This value might need to be fine-tuned***
    94.  /*This sub-section configures the PWM pins as digital outputs*/
    95.  TRISAbits.TRISA3 = 0;  //PWM1L
    96.  TRISAbits.TRISA4 = 0;  //PWM1H
    97.  TRISBbits.TRISB14 = 0; //PWM2L
    98.  TRISBbits.TRISB13 = 0; //PWM2H
    99.  /*End of sub-section*/
    100.  //Now we activate the PWM module
    101.  PTCONbits.PTEN = 1; //PWM activated
    102.  while(1)
    103.  {
    104.  Nop();
    105.  Nop();
    106.  Nop();
    107.  }
    108.  }
    109.  
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    darkfeffy likes this.
  3. darkfeffy

    Thread Starter Member

    Apr 1, 2009
    12
    2
    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?
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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.
     
Loading...