Solution: 2x complemetare pairs pro one CCU8 slice using existing Dave Apps

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User6412
Level 4
Level 4
Hello,

I want to share my simple solution which utilises PWMMP001 app and reconfigure it from assymetric to symmetric PWM mode. Thus the all 4 PWM outputs of CCU8 slices are used (2x complementare pairs).

This problem was already discussed here: http://www.infineonforums.com/threads/790-4-PWM-outputs-from-one-CCU8x-slice

Solution:

1. Add in to the project the PWMMP001 app ("This app generates multi phase PWM centre aligned, asymmetric PWM waveforms with dead time. This app supports trap features along with dither and dead time. It can generate 2, 3 or 4 phase PWM.").

2. After Dave initializations call this additional initialization function (this specifically uses CCU81 unit, only slices 1..3 (3 phases) and initialises additional two PWM outputs per slice):

/**
* This function makes additional initializations of the CCU81 Unit to extend the functionality of
* the already existing PWMMP001 App instance.
*/
void Init_CCU81(void) {
uint8_t PhaseNumber = 0U;
do {
const CCU8PWMLIB_HandleType* HandlePtrLib = PWMMP001_Handle0.PhaseHandlePtr[PhaseNumber];
/*Set the symmetric PWM setting*/
WR_REG(HandlePtrLib->CC8yRegsPtr->CHC, \
CCU8_CC8_CHC_ASE_Msk, CCU8_CC8_CHC_ASE_Pos, CCU8PWMLIB_SYMMETRIC);
/*Configure output (channels 3 and 4) connections as per passive state.*/
WR_REG(HandlePtrLib->CC8yRegsPtr->CHC, \
CCU8_CC8_CHC_OCS3_Msk, CCU8_CC8_CHC_OCS3_Pos, \
~HandlePtrLib->kPassiveState0); // inverted output
WR_REG(HandlePtrLib->CC8yRegsPtr->CHC, \
CCU8_CC8_CHC_OCS4_Msk, CCU8_CC8_CHC_OCS4_Pos, \
HandlePtrLib->kPassiveState1); // direct output
/*Enable and configuration dead time*/
SET_BIT(HandlePtrLib->CC8yRegsPtr->DTC, CCU8_CC8_DTC_DTE1_Pos);
SET_BIT(HandlePtrLib->CC8yRegsPtr->DTC, CCU8_CC8_DTC_DTE2_Pos);
SET_BIT(HandlePtrLib->CC8yRegsPtr->DTC, CCU8_CC8_DTC_DCEN1_Pos);
SET_BIT(HandlePtrLib->CC8yRegsPtr->DTC, CCU8_CC8_DTC_DCEN2_Pos);
SET_BIT(HandlePtrLib->CC8yRegsPtr->DTC, CCU8_CC8_DTC_DCEN3_Pos);
SET_BIT(HandlePtrLib->CC8yRegsPtr->DTC, CCU8_CC8_DTC_DCEN4_Pos);
WR_REG(HandlePtrLib->CC8yRegsPtr->DC1R, CCU8_CC8_DC1R_DT1R_Msk, \
CCU8_CC8_DC1R_DT1R_Pos, HandlePtrLib->kRisingDeadTime);
WR_REG(HandlePtrLib->CC8yRegsPtr->DC2R, CCU8_CC8_DC2R_DT2R_Msk, \
CCU8_CC8_DC2R_DT2R_Pos, HandlePtrLib->kRisingDeadTime);
WR_REG(HandlePtrLib->CC8yRegsPtr->DC1R, CCU8_CC8_DC1R_DT1F_Msk, \
CCU8_CC8_DC1R_DT1F_Pos, HandlePtrLib->kFallingDeadTime);
WR_REG(HandlePtrLib->CC8yRegsPtr->DC2R, CCU8_CC8_DC2R_DT2F_Msk, \
CCU8_CC8_DC2R_DT2F_Pos, HandlePtrLib->kFallingDeadTime);
PhaseNumber++;
} while((PhaseNumber < PWMMP001_Handle0.kNumPhases) && (PWMMP001_Handle0.PhaseHandlePtr[PhaseNumber] != NULL));

/*
* Configure additional 2 outputs per CCU81 slice
*/

/* Configuration of Phase 1 Inverted Output "BL_L1_P" Pin 5.5 */
// Strong driver, sharp edge
WR_REG(PORT5->PDR0, PORT5_PDR0_PD5_Msk, PORT5_PDR0_PD5_Pos, 0);
// Push-pull output
WR_REG(PORT5->IOCR4, PORT_IOCR_PC1_PO_Msk, PORT_IOCR_PC1_PO_Pos, 0);
// ALT3: CCU81.OUT12
WR_REG(PORT5->IOCR4, PORT_IOCR_PC1_PCR_Msk, PORT_IOCR_PC1_PCR_Pos, PORT_IOCR_PCR3);
// Output
WR_REG(PORT5->IOCR4, PORT_IOCR_PC1_OE_Msk, PORT_IOCR_PC1_OE_Pos, PORT_IOCR_OE1);

/* Configuration of Phase 1 Direct Output "HL_L1_P" Pin 5.4 */
// Strong driver, sharp edge
WR_REG(PORT5->PDR0, PORT5_PDR0_PD4_Msk, PORT5_PDR0_PD4_Pos, 0);
// Push-pull output
WR_REG(PORT5->IOCR4, PORT_IOCR_PC0_PO_Msk, PORT_IOCR_PC0_PO_Pos, 0);
// ALT3: CCU81.OUT13
WR_REG(PORT5->IOCR4, PORT_IOCR_PC0_PCR_Msk, PORT_IOCR_PC0_PCR_Pos, PORT_IOCR_PCR3);
// Output
WR_REG(PORT5->IOCR4, PORT_IOCR_PC0_OE_Msk, PORT_IOCR_PC0_OE_Pos, PORT_IOCR_OE1);

/* Configuration of Phase 2 Inverted Output "BL_L2_P" Pin 5.3 */
// Strong driver, sharp edge
WR_REG(PORT5->PDR0, PORT5_PDR0_PD3_Msk, PORT5_PDR0_PD3_Pos, 0);
// Push-pull output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC3_PO_Msk, PORT_IOCR_PC3_PO_Pos, 0);
// ALT3: CCU81.OUT22
WR_REG(PORT5->IOCR0, PORT_IOCR_PC3_PCR_Msk, PORT_IOCR_PC3_PCR_Pos, PORT_IOCR_PCR3);
// Output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC3_OE_Msk, PORT_IOCR_PC3_OE_Pos, PORT_IOCR_OE1);

/* Configuration of Phase 2 Direct Output "HL_L2_P" Pin 5.2 */
// Strong driver, sharp edge
WR_REG(PORT5->PDR0, PORT5_PDR0_PD2_Msk, PORT5_PDR0_PD2_Pos, 0);
// Push-pull output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC2_PO_Msk, PORT_IOCR_PC2_PO_Pos, 0);
// ALT3: CCU81.OUT23
WR_REG(PORT5->IOCR0, PORT_IOCR_PC2_PCR_Msk, PORT_IOCR_PC2_PCR_Pos, PORT_IOCR_PCR3);
// Output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC2_OE_Msk, PORT_IOCR_PC2_OE_Pos, PORT_IOCR_OE1);

/* Configuration of Phase 3 Inverted Output "BL_L3_P" Pin 5.1 */
// Strong driver, sharp edge
WR_REG(PORT5->PDR0, PORT5_PDR0_PD1_Msk, PORT5_PDR0_PD1_Pos, 0);
// Push-pull output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC1_PO_Msk, PORT_IOCR_PC1_PO_Pos, 0);
// ALT3: CCU81.OUT32
WR_REG(PORT5->IOCR0, PORT_IOCR_PC1_PCR_Msk, PORT_IOCR_PC1_PCR_Pos, PORT_IOCR_PCR3);
// Output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC1_OE_Msk, PORT_IOCR_PC1_OE_Pos, PORT_IOCR_OE1);

/* Configuration of Phase 3 Direct Output "HL_L3_P" Pin 5.0 */
// Strong driver, sharp edge
WR_REG(PORT5->PDR0, PORT5_PDR0_PD0_Msk, PORT5_PDR0_PD0_Pos, 0);
// Push-pull output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC0_PO_Msk, PORT_IOCR_PC0_PO_Pos, 0);
// ALT3: CCU81.OUT33
WR_REG(PORT5->IOCR0, PORT_IOCR_PC0_PCR_Msk, PORT_IOCR_PC0_PCR_Pos, PORT_IOCR_PCR3);
// Output
WR_REG(PORT5->IOCR0, PORT_IOCR_PC0_OE_Msk, PORT_IOCR_PC0_OE_Pos, PORT_IOCR_OE1);
}


3. This function let's change the two compare values per one slice (phase):

/**
* Function changes the Compare Register values (CR1 and CR2) for the given phase (0..2)
* Afterwards the shadow transfer request must be explicitly activated.
* Here phase 0 corresponds to L1 etc.
* CR1 corresponds to BH, HH (complementary pair with dead time)
* CR2 corresponds to BL, HL (complementary pair with dead time)
*/
void PWM_SetCompare(PhaseType phase, uint32_t comp1, uint32_t comp2) {
const CCU8PWMLIB_HandleType* HandlePtr = (CCU8PWMLIB_HandleType*) PWMMP001_Handle0.PhaseHandlePtr[phase];
HandlePtr->CC8yRegsPtr->CR1S = (uint32_t)(comp1 & 0xffffU);
HandlePtr->CC8yRegsPtr->CR2S = (uint32_t)(comp2 & 0xffffU);
}


4. After all 6 compare values are changed this function enables the shadow transfer:

/**
* Request Shadow Transfer for all compare values in 3 slices.
*
*/
void PWM_RequestShadowTransfer(void) {
PWMMP001_Handle0.CCU8KernRegsPtr->GCSS |= CCU8_GCSS_S1SE_Msk | CCU8_GCSS_S2SE_Msk | CCU8_GCSS_S3SE_Msk;
}
0 Likes
1 Reply
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
this is cool...:)
0 Likes