XMC4500 PWM CCU4 DUTY CYCLE Problem

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

cross mob
lock attach
Attachments are accessible only for community members.
Not applicable
Hi,


using the example from the attachment, I write code for XMC4500. Programm should generates a PWM signal and an interrupt on every compare match, which alternatesthe PWM's duty cycle between 33.3% and 66.7%. I have a problem because on the osciloscope I don't see any signal, that means the signal is still 0 V.
Do you have any idea what is wrong with my code ?

#include 
#include
#include


#define MODULE_PTR CCU40
#define MODULE_NUMBER (0U)
#define SLICE0_PTR CCU40_CC40
#define SLICE0_NUMBER (0U)
#define SLICE0_OUTPUT P0_0


volatile uint8_t count=1;
uint16_t comparevalue[]=
{
19529U, /* 66.67% duty cycle */
39065 /* 33.33% duty cycle */
};

const XMC_SCU_CLOCK_CONFIG_t CLOCK_XMC4_0_CONFIG =
{
/* N-Divider Value */
.syspll_config.n_div = 80U,
/* P-Divider Value */
.syspll_config.p_div = 2U,
/* K2-Divider Value */
.syspll_config.k_div = 4U,
/* PLL Operating Mode */
.syspll_config.mode = XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL,
/* PLL Clock Source */
.syspll_config.clksrc = XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP,
/* High Precision Oscillator Operating Mode */
.enable_oschp = true,
/* Ultra Low Power Oscillator Setting */
.enable_osculp = false,
/* Calibration Mode */
.calibration_mode = XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_FACTORY,
/* Standby Clock Source */
.fstdby_clksrc = XMC_SCU_HIB_STDBYCLKSRC_OSI,
/* System Clock Source */
.fsys_clksrc = XMC_SCU_CLOCK_SYSCLKSRC_PLL,
/* System Clock Divider Value */
.fsys_clkdiv = 1U,
/* CPU Clock Divider Value */
.fcpu_clkdiv = 1U,
#ifdef CLOCK_XMC4_CCUCLK_ENABLED
/* CCU Clock Divider Value */
.fccu_clkdiv = 1U,
#endif
/* Peripheral Clock Divider Value */
.fperipheral_clkdiv = 1U
};


XMC_CCU4_SLICE_COMPARE_CONFIG_t SLICE0_config =
{
.timer_mode = (uint32_t) XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA,
.monoshot = (uint32_t) false,
.shadow_xfer_clear = (uint32_t) 0,
.dither_timer_period = (uint32_t) 0,
.dither_duty_cycle = (uint32_t) 0,
.prescaler_mode = (uint32_t) XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL,
.mcm_enable = (uint32_t) 0,
.prescaler_initval = (uint32_t) 11, /* in this case, prescaler = 2^10 */
.float_limit = (uint32_t) 0,
.dither_limit = (uint32_t) 0,
.passive_level = (uint32_t) XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.timer_concatenation = (uint32_t) 0
};

XMC_CCU4_SLICE_EVENT_CONFIG_t SLICE0_event0_config=
{
.mapped_input = XMC_CCU4_SLICE_INPUT_I, /* mapped to SCU.GSC40 */
.edge = XMC_CCU4_SLICE_EVENT_EDGE_SENSITIVITY_RISING_EDGE,
.level = XMC_CCU4_SLICE_EVENT_LEVEL_SENSITIVITY_ACTIVE_HIGH,
.duration = XMC_CCU4_SLICE_EVENT_FILTER_3_CYCLES
};


const XMC_GPIO_CONFIG_t PWM_0_gpio_out_config =
{
.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT3,
.output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
.output_strength = XMC_GPIO_OUTPUT_STRENGTH_MEDIUM
};


void CCU40_0_IRQHandler(void)
{
/* Clear pending interrupt */
XMC_CCU4_SLICE_ClearEvent(SLICE0_PTR,XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP);
/* Set new duty cycle value */
XMC_CCU4_SLICE_SetTimerCompareMatch(SLICE0_PTR, comparevalue[count]);
count++;
if(count==2)
{
count=0;
}
/* Enable shadow transfer for the new PWM value update */
XMC_CCU4_EnableShadowTransfer(MODULE_PTR, XMC_CCU4_SHADOW_TRANSFER_SLICE_0);
}



int main(void)
{
XMC_SCU_CLOCK_Init(&CLOCK_XMC4_0_CONFIG);
XMC_CCU4_Init(MODULE_PTR, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU4_StartPrescaler(MODULE_PTR);
XMC_CCU4_SetModuleClock(MODULE_PTR, XMC_CCU4_CLOCK_SCU);
XMC_CCU4_SLICE_CompareInit(SLICE0_PTR, &SLICE0_config);
/* Program duty cycle = 33.33% at 1Hz frequency */
XMC_CCU4_SLICE_SetTimerCompareMatch(SLICE0_PTR, comparevalue[count]);
XMC_CCU4_SLICE_SetTimerPeriodMatch(SLICE0_PTR, 62499U);
/* Enable shadow transfer */
XMC_CCU4_EnableShadowTransfer(MODULE_PTR, \
(uint32_t)(XMC_CCU4_SHADOW_TRANSFER_SLICE_0| \
XMC_CCU4_SHADOW_TRANSFER_PRESCALER_SLICE_0));
/* Enable External Start to Event 0 */
XMC_CCU4_SLICE_ConfigureEvent(SLICE0_PTR, \
XMC_CCU4_SLICE_EVENT_0, &SLICE0_event0_config);
XMC_CCU4_SLICE_StartConfig(SLICE0_PTR, XMC_CCU4_SLICE_EVENT_0, \
XMC_CCU4_SLICE_START_MODE_TIMER_START_CLEAR);
/* Enable compare match events */
XMC_CCU4_SLICE_EnableEvent(SLICE0_PTR, XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP);
/* Connect compare match event to SR0 */
XMC_CCU4_SLICE_SetInterruptNode(SLICE0_PTR, \
XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP, XMC_CCU4_SLICE_SR_ID_0);
/* Set NVIC priority */
NVIC_SetPriority(CCU40_0_IRQn, 3U);
/* Enable IRQ */
NVIC_EnableIRQ(CCU40_0_IRQn);
/* Enable CCU4 PWM output */
XMC_GPIO_Init(XMC_GPIO_PORT1,0, &PWM_0_gpio_out_config);
/* Get the slice out of idle mode */
XMC_CCU4_EnableClock(MODULE_PTR, SLICE0_NUMBER);
XMC_SCU_SetCcuTriggerLow(XMC_SCU_CCU_TRIGGER_CCU40);
XMC_SCU_SetCcuTriggerHigh(XMC_SCU_CCU_TRIGGER_CCU40);


while(1U)
{

}
}


Than you for help.

Best regards
Szymon
0 Likes
5 Replies
DRubeša
Employee
Employee
First solution authored First like received
Hi Szymon,

what board are you exactly using?

Regards,
Deni
0 Likes
Not applicable
Hi
I use XMC4500-F100x1024 Relax

Best regard
Szymon
0 Likes
DRubeša
Employee
Employee
First solution authored First like received
Hi Szymon,

so the reason why I asked you about the board was while I was suspecting that you´re defining wrong output pin for CCU40 slice 0. Take a look at the available options:

2964.attach

So, either you change output pin definition to a pin that is output of CCU40 slice 0, or define different slice, in this case it would be slice 3. But take into consideration also following table. This table is from Board User Manual for your board:

2965.attach

As you can see, pins 1.2.-1.4 are used for on-board SPI Flash memory, and pin 1.0-1.1 are used for LEDs so beware if you use any of those things. Try changing either slice or output pin that you use and let´s see how it will go. Maybe there is additional issue in code 🙂

Regards,
Deni
0 Likes
Not applicable
Hi,
thank you for your reply.
According to your suggestions,I changed the program code and I change output pin to 3.3.
Now on the osciloscope I see high condition all the time.
Do you have any idea what is wrong with my code?

#include 
#include
#include


#define MODULE_PTR CCU42
#define MODULE_NUMBER (2U)
#define SLICE0_PTR CCU42_CC43
#define SLICE0_NUMBER (3U)



volatile uint8_t count=1;
uint16_t comparevalue[]=
{
/* Calculated based on PCLK of 120MHz */
19529U, /* 66.67% duty cycle */
39065 /* 33.33% duty cycle */
};

const XMC_SCU_CLOCK_CONFIG_t CLOCK_XMC4_0_CONFIG =
{
/* N-Divider Value */
.syspll_config.n_div = 80U,
/* P-Divider Value */
.syspll_config.p_div = 2U,
/* K2-Divider Value */
.syspll_config.k_div = 4U,
/* PLL Operating Mode */
.syspll_config.mode = XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL,
/* PLL Clock Source */
.syspll_config.clksrc = XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP,
/* High Precision Oscillator Operating Mode */
.enable_oschp = true,
/* Ultra Low Power Oscillator Setting */
.enable_osculp = false,
/* Calibration Mode */
.calibration_mode = XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_FACTORY,
/* Standby Clock Source */
.fstdby_clksrc = XMC_SCU_HIB_STDBYCLKSRC_OSI,
/* System Clock Source */
.fsys_clksrc = XMC_SCU_CLOCK_SYSCLKSRC_PLL,
/* System Clock Divider Value */
.fsys_clkdiv = 1U,
/* CPU Clock Divider Value */
.fcpu_clkdiv = 1U,
#ifdef CLOCK_XMC4_CCUCLK_ENABLED
/* CCU Clock Divider Value */
.fccu_clkdiv = 1U,
#endif
/* Peripheral Clock Divider Value */
.fperipheral_clkdiv = 1U
};


XMC_CCU4_SLICE_COMPARE_CONFIG_t SLICE0_config =
{
.timer_mode = (uint32_t) XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA,
.monoshot = (uint32_t) false,
.shadow_xfer_clear = (uint32_t) 0,
.dither_timer_period = (uint32_t) 0,
.dither_duty_cycle = (uint32_t) 0,
.prescaler_mode = (uint32_t) XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL,
.mcm_enable = (uint32_t) 0,
.prescaler_initval = (uint32_t) 11, /* in this case, prescaler = 2^10 */
.float_limit = (uint32_t) 0,
.dither_limit = (uint32_t) 0,
.passive_level = (uint32_t) XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.timer_concatenation = (uint32_t) 0
};

XMC_CCU4_SLICE_EVENT_CONFIG_t SLICE0_event0_config=
{
.mapped_input = XMC_CCU4_SLICE_INPUT_I, /* mapped to SCU.GSC40 */
.edge = XMC_CCU4_SLICE_EVENT_EDGE_SENSITIVITY_RISING_EDGE,
.level = XMC_CCU4_SLICE_EVENT_LEVEL_SENSITIVITY_ACTIVE_HIGH,
.duration = XMC_CCU4_SLICE_EVENT_FILTER_3_CYCLES
};


const XMC_GPIO_CONFIG_t PWM_0_gpio_out_config =
{
.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT3,
.output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
.output_strength = XMC_GPIO_OUTPUT_STRENGTH_MEDIUM
};


void CCU40_0_IRQHandler(void)
{
/* Clear pending interrupt */
XMC_CCU4_SLICE_ClearEvent(SLICE0_PTR,XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP);
/* Set new duty cycle value */
XMC_CCU4_SLICE_SetTimerCompareMatch(SLICE0_PTR, comparevalue[count]);
count++;
if(count==2)
{
count=0;
}
/* Enable shadow transfer for the new PWM value update */
XMC_CCU4_EnableShadowTransfer(MODULE_PTR, XMC_CCU4_SHADOW_TRANSFER_SLICE_3);
}



int main(void)
{
XMC_SCU_CLOCK_Init(&CLOCK_XMC4_0_CONFIG);
XMC_CCU4_Init(MODULE_PTR, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU4_StartPrescaler(MODULE_PTR);
XMC_CCU4_SetModuleClock(MODULE_PTR, XMC_CCU4_CLOCK_SCU);
XMC_CCU4_SLICE_CompareInit(SLICE0_PTR, &SLICE0_config);
/* Program duty cycle = 33.33% at 1Hz frequency */
XMC_CCU4_SLICE_SetTimerCompareMatch(SLICE0_PTR, comparevalue[count]);
XMC_CCU4_SLICE_SetTimerPeriodMatch(SLICE0_PTR, 62499U);
/* Enable shadow transfer */
XMC_CCU4_EnableShadowTransfer(MODULE_PTR, \
(uint32_t)(XMC_CCU4_SHADOW_TRANSFER_SLICE_3| \
XMC_CCU4_SHADOW_TRANSFER_PRESCALER_SLICE_3));
/* Enable External Start to Event 0 */
XMC_CCU4_SLICE_ConfigureEvent(SLICE0_PTR, \
XMC_CCU4_SLICE_EVENT_0, &SLICE0_event0_config);
XMC_CCU4_SLICE_StartConfig(SLICE0_PTR, XMC_CCU4_SLICE_EVENT_0, \
XMC_CCU4_SLICE_START_MODE_TIMER_START_CLEAR);
/* Enable compare match events */
XMC_CCU4_SLICE_EnableEvent(SLICE0_PTR, XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP);
/* Connect compare match event to SR0 */
XMC_CCU4_SLICE_SetInterruptNode(SLICE0_PTR, \
XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP, XMC_CCU4_SLICE_SR_ID_0);
/* Set NVIC priority */
NVIC_SetPriority(CCU42_0_IRQn, 3U);
/* Enable IRQ */
NVIC_EnableIRQ(CCU42_0_IRQn);
/* Enable CCU4 PWM output */
XMC_GPIO_Init(XMC_GPIO_PORT3,3, &PWM_0_gpio_out_config);
/* Get the slice out of idle mode */
XMC_CCU4_EnableClock(MODULE_PTR, SLICE0_NUMBER);
XMC_SCU_SetCcuTriggerLow(XMC_SCU_CCU_TRIGGER_CCU42);
XMC_SCU_SetCcuTriggerHigh(XMC_SCU_CCU_TRIGGER_CCU42);


while(1U)
{

}
}


Best regards
Szymon
0 Likes
DRubeša
Employee
Employee
First solution authored First like received
Hi Szymon,

#include 
#include
#include

#define SLICE_PTR CCU42_CC43
#define MODULE_PTR CCU42
#define MODULE_NUMBER (2U)
#define SLICE_NUMBER (3U)

volatile uint8_t count = 1;
uint16_t compareValues[]=
{
/* Calculated based on PCLK of 120MHz */
39065U, /* 33.33% duty cycle */
19529U /* 66.67% duty cycle */
};

const XMC_GPIO_CONFIG_t PWM_0_gpio_out_config =
{
.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT3,
.output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
.output_strength = XMC_GPIO_OUTPUT_STRENGTH_MEDIUM
};

XMC_CCU4_SLICE_COMPARE_CONFIG_t SLICE_config =
{
.timer_mode = (uint32_t) XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA,
.monoshot = (uint32_t) false,
.shadow_xfer_clear = (uint32_t) 0,
.dither_timer_period = (uint32_t) 0,
.dither_duty_cycle = (uint32_t) 0,
.prescaler_mode = (uint32_t) XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL,
.mcm_enable = (uint32_t) 0,
.prescaler_initval = (uint32_t) 11, /* in this case, prescaler = 2^10 */
.float_limit = (uint32_t) 0,
.dither_limit = (uint32_t) 0,
.passive_level = (uint32_t) XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW,
.timer_concatenation = (uint32_t) 0
};

void CCU42_3_IRQHandler(void)
{
/* Set new compare value for both timer slices*/
XMC_CCU4_SLICE_SetTimerCompareMatch(SLICE_PTR, compareValues[count]);

count++;

if (count == 2)
{
count = 0;
}

/* Enable shadow transfer for the new compare values */
XMC_CCU4_EnableShadowTransfer(MODULE_PTR, XMC_CCU4_SHADOW_TRANSFER_SLICE_3);
}

int main(void)
{
/* Ensure fCCU reaches CCU40 */
XMC_CCU4_SetModuleClock(MODULE_PTR, XMC_CCU4_CLOCK_SCU);

XMC_CCU4_Init(MODULE_PTR, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);

/* Start the prescaler and restore clocks to slices */
XMC_CCU4_StartPrescaler(MODULE_PTR);

/* Initialize the Slice */
XMC_CCU4_SLICE_CompareInit(SLICE_PTR, &SLICE_config);

/* Program duty cycle = 33.33% at 1Hz frequency */
XMC_CCU4_SLICE_SetTimerPeriodMatch(SLICE_PTR, 62499U);
XMC_CCU4_SLICE_SetTimerCompareMatch(SLICE_PTR, compareValues[0]);

/* Enable shadow transfer */
XMC_CCU4_EnableShadowTransfer(MODULE_PTR, XMC_CCU4_SHADOW_TRANSFER_SLICE_3);

/* Enable compare match event */
XMC_CCU4_SLICE_EnableEvent(SLICE_PTR, XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP);

/* Connect compare match event to SR3 */
XMC_CCU4_SLICE_SetInterruptNode(SLICE_PTR, XMC_CCU4_SLICE_IRQ_ID_COMPARE_MATCH_UP, XMC_CCU4_SLICE_SR_ID_3);

/* Set priority */
NVIC_SetPriority(CCU42_3_IRQn, 10U);

/* Enable IRQ */
NVIC_EnableIRQ(CCU42_3_IRQn);

/* Initialize GPIO pin */
XMC_GPIO_Init(XMC_GPIO_PORT3, 3, &PWM_0_gpio_out_config);

/* Get the slice out of idle mode */
XMC_CCU4_EnableClock(MODULE_PTR, SLICE_NUMBER);

/* Start timer*/
XMC_CCU4_SLICE_StartTimer(SLICE_PTR);

while(1U)
{

}
}



Please check the code given above...I´ve tried to make your use case with as least code possible. If you really need some SCU clock settings you can added them as well, but this example will still work in the current form.

Regards,
Deni
0 Likes