This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: high resolution preriod is not stable with action qualify ZRO and PRD.

Part Number: TMS320F28379D

Hello, I'm new to programming on microcontrollers. I use one of your products: TMS320F28379D. I code on CCS. I'm looking to make a PWM signal.

I have configured the ePWM output, in up down count as well as a high period resolution with the SFO() file. My problem is as follows: 
I've configured the Action Qualifier to set and toggle when TBCLK reaches Zero and then when it reaches the PRD period. I want to do this because I'm sure I'll have a duty cycle of exactly 50%. The problem is that when I set the qualifying actions to ZRO and PRD (instead of CMPA and CMPB) the HR period is not stable anymore and only varies roughly. Here's an extract from the code:

(*ePWM[j]).AQCTLA.bit.ZRO = AQ_SET;
 (*ePWM[j]).AQCTLA.bit.PRD = AQ_TOGGLE;

But the HR periode signal works perfectly with these lines of code, but it's not what I want:

(*ePWM[j]).AQCTLA.bit.CAU = AQ_SET;
 (*ePWM[j]).AQCTLA.bit.CAD = AQ_CLEAR;

Do you have any idea how to make the HRPWM for the period work with qualified actions on the ZRO and PRD? 
If you need any further information, please do not hesitate to contact me.

This is my full program :

#include "F28x_Project.h"
#include "F2837xD_device.h"
#include "F2837xD_Examples.h"
#include "F2837xD_EPwm_defines.h"                       // init defines
#include "SFO_V8.h"                                     //BESOIN POUR CALIBRER MEP
#include "board.h"                                      //adresse des PWM
#include <stdio.h>



        //----  DEFINITION  ----//


#define LAST_EPWM_INDEX     4


            //-------------- SELECTION DE LA PERIODE ----------------//   
float PeriodeNANOsec = 105;                                                            


            //--------------  GLOBAL  ------------------------//

uint16_t status, PeriodFine,compCount;
int MEP_ScaleFactor = 56 ;
int PRD1,PRD1_HR;
float PRDHRdec;

volatile struct EPWM_REGS *ePWM[] = {0, &EPwm1Regs, &EPwm2Regs, &EPwm3Regs};           //Adresse de chaque EPWM
volatile uint32_t PWM[] = {0, myEPWM1_BASE, myEPWM2_BASE, myEPWM3_BASE};


        //---- APPEL DE FONCTION----//
void PRDcalculation(float32_t periode);
void initGPIO(void);
void initPWM(void);


            //****************** CODE PRINCIPAL***********************//
int main()
{
    PRDcalculation(PeriodeNANOsec);
    // Initialize System Control for Control and Analog Subsystems
    // Enable Peripheral Clocks
    EALLOW;
    InitSysCtrl();
    EDIS;

    // EPWM1A and EPWM1B through all PWMS
    initGPIO();
    DINT;

    // Initialize PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
    EALLOW;
    IER = 0x0000;
    IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xD_DefaultIsr.c.
    // This function is found in F2837xD_PieVect.c.
    InitPieVectTable();

    // Enable global Interrupts and higher priority real-time debug events:
    EINT;   // Enable Global interrupt INTM
    ERTM;   // Enable Global realtime interrupt DBGM

    // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor.
    // HRMSTEP must be populated with a scale factor value prior to enabling
    // high resolution period control.
    while(status == SFO_INCOMPLETE)                             //semble pas util relire le 15-7
    {
        status = SFO();                                         // SFO function returns 2 if an error occurs & # of MEP
        if(status == SFO_ERROR)                                 // steps/coarse step exceeds maximum of 255.
        {
            ESTOP0;
        }
    }


    uint16_t i = 0;
    PeriodFine=0;

    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    initPWM();

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);


    while(1)
    {
        for(PeriodFine = 0x3333; PeriodFine < 0x3334; PeriodFine++)
        {
            for(i=1; i<LAST_EPWM_INDEX; i++)
            {
           
                (*ePWM[i]).TBPRDHR =(PRD1_HR<<8); //In Q16 format
               
            }

            status = SFO(); // in background, MEP calibration module
            // continuously updates MEP_ScaleFactor

            if(status == SFO_ERROR)
            {
                ESTOP0;   // SFO function returns 2 if an error occurs & # of
            }              // MEP steps/coarse step exceeds maximum of 255.
        } // end PeriodFine for loop
    }
}




         //------------------ INITIALISATION HRPWM    --------------//
void initPWM()
{
    uint16_t j;


    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;   // Disable TBCLK within the EPWM
    EDIS;

    for(j=1; j<LAST_EPWM_INDEX; j++)
    {
        //------------------    TIME BASE/ CMP  ---------------------//
        (*ePWM[j]).TBCTL.bit.PRDLD = TB_SHADOW;                     // set Shadow load
        (*ePWM[j]).TBPRD= PRD1;                                     // PWM frequency = 1/(2*TBPRD)
        (*ePWM[j]).CMPA.bit.CMPA = PRD1/2;                          // set duty 50% initially                  //FAcultatif si on utlise le toggle sur le prd et zro
        (*ePWM[j]).CMPA.bit.CMPAHR = (1 << 8);                      // initialize HRPWM extension
        (*ePWM[j]).CMPB.bit.CMPB = PRD1/2;                          // set duty 50% initially
        (*ePWM[j]).CMPB.all |= 1;
        (*ePWM[j]).TBPHS.all = 0;
        (*ePWM[j]).TBCTR = 0;

        (*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;             // Select up-down count mode
        (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
        (*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
        (*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1;                      // TBCLK = SYSCLKOUT
        (*ePWM[j]).TBCTL.bit.FREE_SOFT = 11;

        //------------------    SHADOWS  ---------------------//
        (*ePWM[j]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;              // LOAD CMPA on CTR = 0
        (*ePWM[j]).CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        (*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        (*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;

        //------------------    ACTION QUALIFIER ---------------------//
        (*ePWM[j]).AQCTLA.bit.ZRO = AQ_SET;                         // PWM toggle high/low
        (*ePWM[j]).AQCTLA.bit.PRD = AQ_TOGGLE;

/*
        (*ePWM[j]).AQCTLA.bit.CAU = AQ_SET;                         // PWM toggle high/low
        (*ePWM[j]).AQCTLA.bit.CAD = AQ_CLEAR;
        (*ePWM[j]).AQCTLB.bit.CBU = AQ_CLEAR;                         // PWM toggle high/low
        (*ePWM[j]).AQCTLB.bit.CBD = AQ_SET;         */

        //------------------    HRPWM  ---------------------//
        EALLOW;
        (*ePWM[j]).HRCNFG.all = 0x0;

        (*ePWM[j]).HRCNFG.bit.EDGMODE = HR_BEP;                 // MEP control on  both edges.
        (*ePWM[j]).HRCNFG.bit.CTLMODE = HR_CMP;                 // CMPAHR and TBPRDHR HR control.
        (*ePWM[j]).HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD;         // load on CTR = 0  and CTR = TBPRD

        (*ePWM[j]).HRCNFG.bit.EDGMODEB = HR_BEP;                // MEP control on  both edges
        (*ePWM[j]).HRCNFG.bit.CTLMODEB = HR_CMP;                // CMPBHR and TBPRDHR   HR control
        (*ePWM[j]).HRCNFG.bit.HRLOADB = HR_CTR_ZERO_PRD;        // load on CTR = 0  and CTR = TBPRD


        (*ePWM[j]).HRCNFG.bit.AUTOCONV = 1;                     // Enable autoconversion for HR period
        (*ePWM[j]).HRPCTL.bit.TBPHSHRLOADE = 1;                 // Enable TBPHSHR sync  (required for updwn count HR control)
        (*ePWM[j]).HRPCTL.bit.HRPE = 1;                         // Turn on high-resolution period control.
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;                   // Enable TBCLK within the EPWM
        (*ePWM[j]).TBCTL.bit.SWFSYNC = 1;                       // Synchronize high resolution phase to start HR period

      

        EDIS;

    }
}


        //------------------ INITIALISATION GPIO      --------------//
void initGPIO()
{
    EALLOW;                                                
    // CONFIGURER GPIO 0 POUR PWM1A
    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;                 
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;            
    // CONFIGURER GPIO 1 POUR PWM1B
    GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;                   
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;                  
    EDIS;                                                
}

void PRDcalculation(float32_t periode)
{
   float Number_TBCLK=0;                                                        // Nombre de coup d'horlogie avec TBCLK=10ns
   float invTBCLK= 0.10;                                                        //  1/TBCLK = 0.1 in nanosec
   Number_TBCLK = periode*invTBCLK;                                           
   int integer_Number_TBCLK = (Number_TBCLK);                                  
   PRD1 = integer_Number_TBCLK/2;                                              
   PRDHRdec = (((Number_TBCLK-integer_Number_TBCLK)*MEP_ScaleFactor+0.5)*2);
   PRD1_HR=(PRDHRdec);
}