http://www.ti.com.cn/cn/lit/an/tidu312/tidu312.pdf

http://www.ti.com.cn/cn/lit/an/slua712/slua712.pdf

Designing a UCD3138 Controlled Interleaved PFCBosheng Sun High Performance Isolated

http://www.st.com/content/ccc/resource/technical/document/application_note/group0/9e/cc/b1/4a/5d/c8/4a/64/DM00333800/files/DM00333800.pdf/jcr:content/translations/en.DM00333800.pdf

https://www.st.com/content/ccc/resource/technical/document/application_note/fa/f1/fe/3d/81/1e/47/45/DM00050692.pdf/files/DM00050692.pdf/jcr:content/translations/en.DM00050692.pdf

http://ww1.microchip.com/downloads/en/AppNotes/01106A.pdf

http://www.ti.com/lit/an/slua079/slua079.pdf

http://www.ti.com/lit/an/slua896/slua896.pdf

http://www.ti.com/lit/ml/slyy131/slyy131.pdf

https://www.ti.com/seclit/ml/slup203/slup203.pdf

http://www.rolfes.org/kevin_rolfes_msee_thesis.pdf

https://www.infineon.com/dgdl/APP_XMC4000_PFC_Example_Code_v1_0.exe?fileId=db3a30433fa3001d013fa46cca63035a


https://www.infineon.com/dgdl/APP_XMC4000_PFC_v1_0.pdf?fileId=db3a30433f74fc8b013f7549c9430047


/*******************************************************************************
 Copyright (c) 2013, Infineon Technologies AG                                 **
 All rights reserved.                                                         **
                                                                              **
 Redistribution and use in source and binary forms, with or without           **
 modification,are permitted provided that the following conditions are met:   **
                                                                              **
 *Redistributions of source code must retain the above copyright notice,      **
 this list of conditions and the following disclaimer.                        **
 *Redistributions in binary form must reproduce the above copyright notice,   **
 this list of conditions and the following disclaimer in the documentation    **
 and/or other materials provided with the distribution.                       **
 *Neither the name of the copyright holders nor the names of its contributors **
 may be used to endorse or promote products derived from this software without**
 specific prior written permission.                                           **
                                                                              **
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  **
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE    **
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE   **
 ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE   **
 LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR         **
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF         **
 SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    **
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN      **
 CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)       **
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE   **
 POSSIBILITY OF SUCH DAMAGE.                                                  **
                                                                              **
 To improve the quality of the software, users are encouraged to share        **
 modifications, enhancements or bug fixes with Infineon Technologies AG       **
 dave@infineon.com).                                                          **
                                                                              **
********************************************************************************
**                                                                            **
**                                                                            **
** PLATFORM : Infineon XMC4000 Series                                         **
**                                                                            **
** COMPILER : Compiler Independent                                            **
**                                                                            **
** AUTHOR   : Application Engineering                                         **
**                                                                            **
** MAY BE CHANGED BY USER [yes/no]: Yes                                       **
**                                                                            **
** MODIFICATION DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/
/*******************************************************************************
**                      Author(s) Identity                                    **
********************************************************************************
**                                                                            **
** Initials     Name                                                          **
** ---------------------------------------------------------------------------**
** HLM        Application Engineering                                         **
*******************************************************************************/
/**
 * @file   main.c
 * @brief  Main.c file for PFC operating in CCM, Avg Current Mode Ctrl
 *
 */


/*******************************************************************************
**                      Include Files                                         **
*******************************************************************************/
/* Inclusion of header file */
#include <DAVE3.h> //Declarations from DAVE3 Code Generation (includes SFR declaration)
#include "GPIO.h"
#include "PFC.h"
#include "arm_math.h"


/*******************************************************************************
**                      Global Constant Definitions                           **
*******************************************************************************/
#define HIGH_LINE


#define N_VIN 0.166f
#define N_VOUT 0.166f
#define OUTPUTVOLTAGE_REF 400.0f


#define BLOCK_SIZE 1
#define NUM_TAPS 12


__IO uint32_t *ShadowCompareReg;
__IO uint32_t *ShadowTransfer;
__IO uint32_t *ADCResult_Vin;
__IO uint32_t *ADCResult_Vout;
__IO uint32_t *ADCResult_Current;


/*******************************************************************************
**                      Global Variable Definitions                           **
*******************************************************************************/
uint16_t uwInductorCurrent;
uint16_t uwOutputVoltage;
uint16_t uwInputVoltage;
uint16_t FIR_DelayCounter;
uint16_t OverVoltageBit;
uint16_t qADCUpperBound;
uint16_t qADCLowerBound;
uint16_t qOverVoltageCount;
uint16_t qUnderVoltageCount;


float fADCUpperBound;
float fADCLowerBound;


uint32_t blockSize = BLOCK_SIZE;


static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1];


volatile float fOpAmpOffset;


volatile unsigned long timingdelay;


volatile PFC_Coefs_Type PFC;


arm_pid_instance_f32 PI_Current;
arm_pid_instance_f32 PI_Voltage;
arm_fir_instance_f32 sFIR;


/*******************************************************************************
**                      Private Constant Definitions                          **
*******************************************************************************/
const float32_t firCoeffs32[NUM_TAPS] =
{0.0056f, 0.0158f, 0.0467f, 0.0967f, 0.1503f, 0.1850f, 0.1850f, 0.1503f, 0.0967f, 0.0467f, 0.0158f, 0.0056f};


/*******************************************************************************
**                      Public Function Definitions                           **
*******************************************************************************/
void Delay100us(unsigned long time);


void PFC_Init(void);
void ControlLoop_Init(void);
void Current_Offset_Measurement(void);
void arm_fir_f32_1(const arm_fir_instance_f32 *S, float32_t *pSrc, float32_t *pDst);


/*******************************************************************************
**                                                                            **
** FUNCTION : int main(void)   **
**   **
** DESCRIPTION : This is the main function of the PFC code    **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                        **
**                                                                            **
*******************************************************************************/


int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)


// at CLK001 App: Set Back Up Clock Trimming Option to "Backup Clock Factory Calibrated"


DAVE_Init(); // Initialization of DAVE Apps


/* Set system timer to 100us */
SysTick_Config(12000);


/* Change the interrupt setting from Period Match to One Match Interrupt. Take note of the CCU4x/CC4x used */
WR_REG(CCU40_CC40->INTE, CCU4_CC4_INTE_PME_Msk, CCU4_CC4_INTE_PME_Pos, 0);
WR_REG(CCU40_CC40->INTE, CCU4_CC4_INTE_OME_Msk, CCU4_CC4_INTE_OME_Pos, 1);


/* Initialize pointers to corresponding registers */
ADCResult_Current = &ADCCH001_Handle0.ADCGrPtr->RES[ADCCH001_Handle0.kEndResultRegNo];
ADCResult_Vout = &ADCCH001_Handle1.ADCGrPtr->RES[ADCCH001_Handle1.kEndResultRegNo];
ADCResult_Vin = &ADCCH001_Handle2.ADCGrPtr->RES[ADCCH001_Handle2.kEndResultRegNo];
ShadowCompareReg = &PWMSP001_Handle0.CC4yRegsPtr->CRS;
ShadowTransfer = &PWMSP001_Handle0.CC4yKernRegsPtr->GCSS;


/* Initialize ADC Queue */
ADC002_InitializeQueue(&ADC002_Handle0);


/* Set Output Voltage Lower and Higher Boundary for STARTUP OPERATION */
fADCUpperBound = 480.0f / N_VOUT;
fADCLowerBound = 0.0f / N_VOUT;
qADCUpperBound = (uint32_t) fADCUpperBound;
qADCLowerBound = (uint32_t) fADCLowerBound;


/* Set Output Voltage Upper Boundary (Boundary1) and Lower Boundary (Boundary0) */
WR_REG(ADCGROUP001_Handle0.VADCGroupPtr->BOUND, VADC_G_BOUND_BOUNDARY1_Msk, VADC_G_BOUND_BOUNDARY1_Pos, qADCUpperBound);
WR_REG(ADCGROUP001_Handle0.VADCGroupPtr->BOUND, VADC_G_BOUND_BOUNDARY0_Msk, VADC_G_BOUND_BOUNDARY0_Pos, qADCLowerBound);


/* Initialize Current Loop PI controller coefficients AC-DC Converter */
PI_Current.Kp = 0.0f;
PI_Current.Ki = 0.0f;
PI_Current.Kd = 0.0f;
arm_pid_init_f32(&PI_Current, 1);


/* Initialize Voltage Loop PI controller coefficients */
PI_Voltage.Kp = 0.0;
PI_Voltage.Ki = 0.0;
PI_Voltage.Kd = 0.0;
arm_pid_init_f32(&PI_Voltage, 1);


/* Start CCU4 Slices */
PWMSP001_Start(&PWMSP001_Handle0);
PWMSP001_Start(&PWMSP001_Handle1);


/* Delay 500ms to wait for OpAmp output to stabilize */
Delay100us(5000);


/* Measure OpAmp Offset */
Current_Offset_Measurement();


/* Initialize PFC variables */
PFC_Init();


/* Enable Period Match and Compare Match interrupts for Voltage and Current Loop */
NVIC002_EnableIRQ(&NVIC002_Handle0);
NVIC002_EnableIRQ(&NVIC002_Handle1);


/* Delay 50ms to wait for FIR filter to stabilise */
Delay100us(500);


/* Initialize PI controllers coefficients for Voltage and Current Loops */
ControlLoop_Init();


/* Enable Overvoltage Interrupt */
NVIC002_EnableIRQ(&NVIC002_Handle2);


/* Delay until PFC Steady State operation is reached */
Delay100us(5000);
Delay100us(5000);


/* Set Output Voltage Lower and Higher Boundary for STEADY STATE OPERATION */
fADCUpperBound = 450.0f / N_VOUT;
fADCLowerBound = 370.0f / N_VOUT;
qADCUpperBound = (uint32_t) fADCUpperBound;
qADCLowerBound = (uint32_t) fADCLowerBound;


/* Set Output Voltage Upper Boundary (Boundary1) and Lower Boundary (Boundary0) */
WR_REG(ADCGROUP001_Handle0.VADCGroupPtr->BOUND, VADC_G_BOUND_BOUNDARY1_Msk, VADC_G_BOUND_BOUNDARY1_Pos, qADCUpperBound);
WR_REG(ADCGROUP001_Handle0.VADCGroupPtr->BOUND, VADC_G_BOUND_BOUNDARY0_Msk, VADC_G_BOUND_BOUNDARY0_Pos, qADCLowerBound);


while(1)
{


}
return 0;
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void PeriodMatch_INT(void)   **
**   **
** DESCRIPTION : This is the Interrupt Service Routine for   **
** CCU4 Period Match event. It is used for Current Loop   **
** and updating PWM duty cycle.   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                        **
**                                                                            **
*******************************************************************************/


void PeriodMatch_INT(void)
{
volatile uint16_t tempInductorCurrent;


/* Read Input Voltage */
PFC.qVin = *ADCResult_Vin;
PFC.fVin = (float)PFC.qVin * PFC.fN_Vin;


/* Read Inductor Current */
tempInductorCurrent = *ADCResult_Current;
PFC.fIpfc = (float)tempInductorCurrent;
PFC.fIpfc = PFC.fIpfc - fOpAmpOffset;


/* Calculate Current Command */
PFC.fCurrentCmdOut = PFC.fVin * PFC.fInvSqr * PFC.fPI_VoltageOut;


/* Current Loop Calculation for AC-DC Converter */
PFC.fPI_CurrentOut = arm_pid_f32(&PI_Current, (PFC.fCurrentCmdOut - PFC.fIpfc));


if (OverVoltageBit == 0)
{
/* Update PWM for Current Control */
*ShadowCompareReg = (uint16_t) (PFC.fPI_CurrentOut);


/* Limit PWM duty cycle */
if(*ShadowCompareReg > PFC.qPWM_Current_MAX)
{
*ShadowCompareReg = PFC.qPWM_Current_MAX;
}
}
else
{
/* Turn off PWM */
*ShadowCompareReg = 0;
}


/* Enable Shadow Transfer for Slice 0 */
*ShadowTransfer = 0x01;
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void CompareMatch_INT(void)   **
**   **
** DESCRIPTION : This is the Interrupt Service Routine for   **
** CCU4 Compare Match event. It is used for Output Voltage  **
** Loop and Feedforward Filter   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/


void CompareMatch_INT(void)
{
/* Read Output Voltage */
PFC.qVout = *ADCResult_Vout;
PFC.fVout = (float)PFC.qVout * PFC.fN_Vout;


/* Voltage Loop Calculation */
PFC.fPI_VoltageOut = arm_pid_f32(&PI_Voltage, (PFC.fVoltageRef - PFC.fVout));


/* FIR filter */
FIR_DelayCounter--;
while(FIR_DelayCounter == 0)
{
/* FIR Filter */
arm_fir_f32_1(&sFIR, &PFC.fVin, &PFC.fFilterResult);


/* Calculate Inverse Square */
PFC.fInvSqr = 1.0f / (PFC.fFilterResult * PFC.fFilterResult);
FIR_DelayCounter = 40;
}
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void Overvoltage_INT(void)   **
**   **
** DESCRIPTION : This is the Interrupt Service Routine for   **
** VADC Channel Event Interrupt. It is used as overvoltage  **
** handler.   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                            **
**                                                                            **
*******************************************************************************/


void Overvoltage_INT(void)
{
/* Upper Boundary Interrupt */
if ((PFC.qVout > qADCUpperBound) && !OverVoltageBit)
{
/* Sample OverVoltage Interrupt occurrence for 500 times (5ms) */
qOverVoltageCount++;


if (qOverVoltageCount > 500)
{
/* Turn On OverVoltage Bit */
OverVoltageBit = 1;


/* Reset PI Controllers */
arm_pid_reset_f32(&PI_Current);
arm_pid_reset_f32(&PI_Voltage);


/* Reset OverVoltage Counter */
qOverVoltageCount = 0;
}
}


/* Lower Boundary Interrupt */
else if ((PFC.qVout < qADCLowerBound) && OverVoltageBit)
{
/* Sample UnderVoltage Interrupt occurrence for 500 times (5ms) */
qUnderVoltageCount++;


if(qUnderVoltageCount > 500)
{
/* Turn Off OverVoltage Bit */
OverVoltageBit = 0;


/* Enable PI Controllers */
ControlLoop_Init();


/* Reset UnderVoltage Counter */
qUnderVoltageCount = 0;
}
}
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void PFC_Init(void)   **
**   **
** DESCRIPTION : This function is to initialize PFC parameters and   **
** Feedforward Filter   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/


void PFC_Init(void)
{
/* Initialize FIR Filter */
arm_fir_init_f32(&sFIR, NUM_TAPS, (float32_t *)&firCoeffs32[0], &firStateF32[0], blockSize);


/* Assign values to PFC struct */
PFC.fN_Vin = N_VIN;
PFC.fN_Vout = N_VOUT;
PFC.fVoltageRef = OUTPUTVOLTAGE_REF;
FIR_DelayCounter = 40;


/* Determine Maximum Duty Cycle from CCU4 Period Register. In this case it is 80% */
PFC.qPWM_Current_MAX = (PWMSP001_Handle0.CC4yRegsPtr->PRS * 9.6) / 10;


/* Initialize OverVoltage Conditions to 0 during startup */
OverVoltageBit = 0;
qOverVoltageCount = 0;
qUnderVoltageCount = 0;
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void ControlLoop_Init(void)   **
**   **
** DESCRIPTION : This function is to initialize Current and Voltage Loop   **
** Parameters (Kp and Ki)   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/


void ControlLoop_Init(void)
{
#ifdef HIGH_LINE
/* Initialize Current Loop PI controller coefficients AC-DC Converter */
PI_Current.Kp = 0.036f/2; /* high line */
PI_Current.Ki = 0.02f/2; /* high line */
PI_Current.Kd = 0.0f;
arm_pid_init_f32(&PI_Current, 1);


/* Initialize Voltage Loop PI controller coefficients */
PI_Voltage.Kp = 0.01f; /* high line */
PI_Voltage.Ki = 0.04f*15; /* high line */
PI_Voltage.Kd = 0.0f;
arm_pid_init_f32(&PI_Voltage, 1);
#else
/* Initialize Current Loop PI controller coefficients AC-DC Converter */
PI_Current.Kp = 0.04/2; /* low line */
PI_Current.Ki = 0.022/10; /* low line */
PI_Current.Kd = 0.0f;
arm_pid_init_f32(&PI_Current, 1);


/* Initialize Voltage Loop PI controller coefficients */
PI_Voltage.Kp = 0.01f/4; /* low line */
PI_Voltage.Ki = 0.04f*10; /* low line */
PI_Voltage.Kd = 0.0f;
arm_pid_init_f32(&PI_Voltage, 1);
#endif
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void Current_Offset_Measurement(void)   **
**   **
** DESCRIPTION : This function is to measure the Current Op-Amp Offset   **
** in the beginning   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/


void Current_Offset_Measurement(void)
{
uint16_t MeasurementCount = 0;
uint32_t ulOpAmpOffset = 0;


while (MeasurementCount < 32)
{
/* Read Inductor Current from ADC Result Register */
ADCCH001_GetResult(&ADCCH001_Handle0, &uwInductorCurrent);


/* Accumulate Inductor Current reading for 32 times */
ulOpAmpOffset += (uwInductorCurrent & 0x0FFF);
MeasurementCount++;
}


/* Find the Op-Amp Current Sense average by dividing the accumulated readings */
fOpAmpOffset = (float)ulOpAmpOffset / 32.0;
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void Delay100us(unsigned long time)   **
**   **
** DESCRIPTION : This function produces 100us delay time   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/


void Delay100us(unsigned long time)
{
unsigned long t, m;


timingdelay = time;
for(t = timingdelay; t>0; t--)
{
for(m = 1000; m>0; m--);
}
}


void SysTick_Handler(void)
{
if(timingdelay != 0)
{
timingdelay--;
}
}


/*******************************************************************************
**                                                                            **
** FUNCTION : void arm_fir_f32_1( , , )     **
**   **
** DESCRIPTION : This is Feedfoward Filter function   **
**                                                                            **
** VERSION : 1.0.0 (Initial version)   **
**                                                                            **
** DATE : Jul 01, 2013                                           **
**                                                                            **
*******************************************************************************/


void arm_fir_f32_1(const arm_fir_instance_f32 * S, float32_t * pSrc, float32_t * pDst)
{
  float32_t *pState = S->pState;                 /* State pointer */
  float32_t *pCoeffs = S->pCoeffs;               /* Coefficient pointer */
  float32_t *pStateCurnt;                        /* Points to the current sample of the state */
  float32_t *px, *pb;                            /* Temporary pointers for state and coefficient buffers */
  uint32_t numTaps = S->numTaps;                 /* Number of filter coefficients in the filter */
  uint32_t i, tapCnt;                            /* Loop counters */


  float32_t acc0;              /* Accumulators */


  /* S->pState points to state array which contains previous frame (numTaps - 1) samples */
  /* pStateCurnt points to the location where the new input data should be written */
  pStateCurnt = &(S->pState[(numTaps - 1u)]);


    /* Copy one sample at a time into state buffer */
    *pStateCurnt++ = *pSrc++;


    /* Set the accumulator to zero */
    acc0 = 0.0f;


    /* Initialize state pointer */
    px = pState;


    /* Initialize Coefficient pointer */
    pb = (pCoeffs);


    i = numTaps;


    /* Perform the multiply-accumulates */
    do
    {
      acc0 += *px++ * *pb++;
      i--;


    } while(i > 0u);


    /* The result is store in the destination buffer. */
    *pDst++ = acc0;


    /* Advance state pointer by 1 for the next sample */
    pState = pState + 1;


  /* Processing is complete.
   ** Now copy the last numTaps - 1 samples to the satrt of the state buffer.
   ** This prepares the state buffer for the next function call. */


  /* Points to the start of the state buffer */
  pStateCurnt = S->pState;


  tapCnt = (numTaps - 1u) >> 2u;


  /* copy data */
  while(tapCnt > 0u)
  {
    *pStateCurnt++ = *pState++;
    *pStateCurnt++ = *pState++;
    *pStateCurnt++ = *pState++;
    *pStateCurnt++ = *pState++;


    /* Decrement the loop counter */
    tapCnt--;
  }


  /* Calculate remaining number of copies */
  tapCnt = (numTaps - 1u) % 0x4u;


  /* Copy the remaining q31_t data */
  while(tapCnt > 0u)
  {
    *pStateCurnt++ = *pState++;


    /* Decrement the loop counter */
    tapCnt--;
  }
}

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐