📄 example_2833xhrpwm_sfo_v5.c
字号:
MEP_ScaleFactor[i] =0;
}
// MEP_ScaleFactor variables intialization using SFO_MepDis_V5 library function.
for(i=1;i<PWM_CH;i++)
{
while ( SFO_MepDis_V5(i) == SFO_INCOMPLETE ); //returns "0" when cal. incomplete for channel
}
// Initialize a common seed variable MEP_ScaleFactor[0] required for all SFO functions
MEP_ScaleFactor[0] = MEP_ScaleFactor[1];
// Some useful Period vs Frequency values
// SYSCLKOUT = 150MHz 100 MHz
// -----------------------------------------
// Period Frequency Frequency
// 1000 150 kHz 100 KHz
// 800 187 kHz 125 KHz
// 600 250 kHz 167 KHz
// 500 300 kHz 200 KHz
// 250 600 kHz 400 KHz
// 200 750 kHz 500 KHz
// 100 1.5 MHz 1.0 MHz
// 50 3.0 MHz 2.0 MHz
// 25 6.0 MHz 4.0 MHz
// 20 7.5 MHz 5.0 MHz
// 12 12.5 MHz 8.33 MHz
// 10 15.0 MHz 10.0 MHz
// 9 16.7 MHz 11.1 MHz
// 8 18.8 MHz 12.5 MHz
// 7 21.4 MHz 14.3 MHz
// 6 25.0 MHz 16.7 MHz
// 5 30.0 MHz 20.0 MHz
//====================================================================
// ePWM and HRPWM register initialization
//====================================================================
HRPWM_Config(30); // ePWMx target, 5 MHz PWM (150MHz SYSCLKOUT)/3.33 MHz PWM (100MHz SYSCLKOUT)
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
for(;;)
{
// Sweep DutyFine as a Q15 number from 0.2 - 0.999
for(DutyFine = 0x2300; DutyFine < 0x7000; DutyFine++)
{
if(UpdateFine)
{
/*
// CMPA_reg_val is calculated as a Q0.
// Since DutyFine is a Q15 number, and the period is Q0
// the product is Q15. So to store as a Q0, we shift right
// 15 bits.
CMPA_reg_val = ((long)DutyFine * EPwm1Regs.TBPRD)>>15;
// This next step is to obtain the remainder which was
// truncated during our 15 bit shift above.
// compute the whole value, and then subtract CMPA_reg_val
// shifted LEFT 15 bits:
temp = ((long)DutyFine * EPwm1Regs.TBPRD) ;
temp = temp - ((long)CMPA_reg_val<<15);
// This obtains the MEP count in digits, from
// 0,1, .... MEP_Scalefactor. Once again since this is Q15
// convert to Q0 by shifting:
CMPAHR_reg_val = (temp*MEP_ScaleFactor[1])>>15;
// Now the lower 8 bits contain the MEP count.
// Since the MEP count needs to be in the upper 8 bits of
// the 16 bit CMPAHR register, shift left by 8.
CMPAHR_reg_val = CMPAHR_reg_val << 8;
// Add the offset and rounding
CMPAHR_reg_val += 0x0180;
// Write the values to the registers as one 32-bit or two 16-bits
EPwm1Regs.CMPA.half.CMPA = CMPA_reg_val;
EPwm1Regs.CMPA.half.CMPAHR = CMPAHR_reg_val;
*/
// All the above operations may be condensed into
// the following form for each channel:
// EPWM calculations where EPwm1Regs are accessed
// by (*ePWM[1]), EPwm2Regs are accessed by (*ePWM[2]),
// etc.:
for(i=1;i<PWM_CH;i++)
{
CMPA_reg_val = ((long)DutyFine * (*ePWM[i]).TBPRD)>>15;
temp = ((long)DutyFine * (*ePWM[i]).TBPRD) ;
temp = temp - ((long)CMPA_reg_val<<15);
CMPAHR_reg_val = (temp*MEP_ScaleFactor[i])>>15;
CMPAHR_reg_val = CMPAHR_reg_val << 8;
CMPAHR_reg_val += 0x0180;
// Example for a 32 bit write to CMPA:CMPAHR
(*ePWM[i]).CMPA.all = ((long)CMPA_reg_val)<<16 | CMPAHR_reg_val;
}
}
else
{
// CMPA_reg_val is calculated as a Q0.
// Since DutyFine is a Q15 number, and the period is Q0
// the product is Q15. So to store as a Q0, we shift right
// 15 bits.
for(i=1;i<PWM_CH;i++)
{
(*ePWM[i]).CMPA.half.CMPA = ((long)DutyFine * (*ePWM[i]).TBPRD>>15);
}
}
// Call the scale factor optimizer lib function SFO_MepEn_V5()
// periodically to track for any changes due to temp/voltage.
// SFO_MepEn_V5 Calibration must be finished on one channel (return 1) before
// moving on to the next channel.
//
// *NOTE*: In this example, SFO_MepEn_V5 is called 700 times in a loop. For example
// purposes, this allows the CMPAHR and CMPA registers to change in such
// a way that when watching in "Continuous Refresh" mode, the user
// can see the CMPAHR register increment in fine steps to a certain point
// before the CMPA register increments in a coarse step. Normally,
// SFO_MepEn_V5 can be called once every so often in the background for
// a slow update with no for-loop.
for (i=0; i<700; i++) // Call SFO_MepEn_V5 700 times.
{
status = SFO_MepEn_V5(nMepChannel);
if (status == SFO_COMPLETE) // Once SFO_MepEn_V5 complete (returns 1)-
nMepChannel++; // move on to next channel
else if (status == SFO_OUTRANGE_ERROR) // If MEP_ScaleFactor[nMepChannel] differs
{ // from seed Mep_ScaleFactor[0] by more than
error(); // +/-15, status = 2 (out of range error)
}
if(nMepChannel==PWM_CH)
nMepChannel =1; // Once max channels reached, loop back to channel 1
}
} // end DutyFine for loop
} // end infinite for loop
} // end SFO_MepEn_V5
//=============================================================
// FUNCTION: HRPWM_Config
// DESCRIPTION: Configures all ePWM channels and sets up HRPWM
// on ePWMxA channels
//
// PARAMETERS: period - desired PWM period in TBCLK counts
// RETURN: N/A
//=============================================================
void HRPWM_Config(period)
{
Uint16 j;
// ePWM channel register configuration with HRPWM
// ePWMxA toggle low/high with MEP control on Rising edge
for (j=1;j<PWM_CH;j++)
{
(*ePWM[j]).TBCTL.bit.PRDLD = TB_IMMEDIATE; // set Immediate load
(*ePWM[j]).TBPRD = period-1; // PWM frequency = 1 / period
(*ePWM[j]).CMPA.half.CMPA = period / 2; // set duty 50% initially
(*ePWM[j]).CMPA.half.CMPAHR = (1 << 8); // initialize HRPWM extension
(*ePWM[j]).CMPB = period / 2; // set duty 50% initially
(*ePWM[j]).TBPHS.all = 0;
(*ePWM[j]).TBCTR = 0;
(*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UP;
(*ePWM[j]).TBCTL.bit.PHSEN = TB_DISABLE;
(*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
(*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
(*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1;
(*ePWM[j]).TBCTL.bit.FREE_SOFT = 11;
(*ePWM[j]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
(*ePWM[j]).CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
(*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
(*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;
(*ePWM[j]).AQCTLA.bit.ZRO = AQ_SET; // PWM toggle high/low
(*ePWM[j]).AQCTLA.bit.CAU = AQ_CLEAR;
(*ePWM[j]).AQCTLB.bit.ZRO = AQ_SET;
(*ePWM[j]).AQCTLB.bit.CBU = AQ_CLEAR;
EALLOW;
(*ePWM[j]).HRCNFG.all = 0x0;
(*ePWM[j]).HRCNFG.bit.EDGMODE = HR_FEP; // MEP control on falling edge
(*ePWM[j]).HRCNFG.bit.CTLMODE = HR_CMP;
(*ePWM[j]).HRCNFG.bit.HRLOAD = HR_CTR_ZERO;
EDIS;
}
}
//=============================================================
// FUNCTION: error
// DESCRIPTION: An error occurs when the MEP_ScaleFactor [n]
// calculated from SFO_MEPEn_V5 differs by > +/- 15
// from the Seed Value in MEP_ScaleFactor[0].
// SFO_MepEn_V5 returned a "2" (SFO_OUTRANGE_ERROR).
// The user should:
// (1) Re-run SFO_MepDis_V5 to re-calibrate
// an appropriate seed value.
// (2) Ensure the code is not calling Mep_En_V5
// on a different channel when it is currently
// still running on a channel. (Repetitively
// call Mep_En_V5 on current channel until an
// SFO_COMPLETE ( i.e. 1) is returned.
// (3) If the out-of-range condition is acceptable
// for the application, ignore the "2" and
// treat it as a "1" or SFO_COMPLETE.
//
// PARAMETERS: N/A
// RETURN: N/A
//=============================================================
void error (void)
{
ESTOP0; // Error - MEP_ScaleFactor out of range of Seed - rerun MepDis calibration.
}
// No more
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -