Feb 20, 2018
01:58 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Feb 20, 2018
01:58 AM
I am trying to generate a PWM with a 32Bit resolution and 50% duty-cycle on P3.7 using CCU41_CC42 and CCU41_CC43. I wrote the following code to initialize the hardware:
The following function is used to set the period and duty-cycle (fixed to 50%):
This all works fine with a period up to 0xFFFF. Everything above that (more than 16Bit set) deactivates the PWM output. Using the debugger I can see that the timer itself is running and the registers are set correctly. What am I doing wrong?
const XMC_GPIO_CONFIG_t PWM_pin_config =
{
XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT3, //Mode
XMC_GPIO_OUTPUT_LEVEL_LOW, //level
XMC_GPIO_OUTPUT_STRENGTH_MEDIUM //strength
};
XMC_GPIO_Init(P3_7, &PWM_pin_config);
XMC_CCU4_SLICE_COMPARE_CONFIG_t SLICE_config;
SLICE_config.timer_mode = (uint32_t) XMC_CCU4_SLICE_TIMER_COUNT_MODE_EA;
SLICE_config.monoshot = (uint32_t) false;
SLICE_config.shadow_xfer_clear = (uint32_t) 0;
SLICE_config.dither_timer_period = (uint32_t) 0;
SLICE_config.dither_duty_cycle = (uint32_t) 0;
SLICE_config.prescaler_mode = (uint32_t) XMC_CCU4_SLICE_PRESCALER_MODE_NORMAL;
SLICE_config.mcm_enable = (uint32_t) 0;
SLICE_config.prescaler_initval = (uint32_t) XMC_CCU4_SLICE_PRESCALER_1;
SLICE_config.float_limit = (uint32_t) 0;
SLICE_config.dither_limit = (uint32_t) 0;
SLICE_config.passive_level = (uint32_t) XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_LOW;
SLICE_config.timer_concatenation = (uint32_t) 0;
XMC_CCU4_Init(CCU41, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR);
XMC_CCU4_StartPrescaler(CCU41);
XMC_CCU4_SetModuleClock(CCU41, XMC_CCU4_CLOCK_SCU);
XMC_CCU4_SLICE_CompareInit(CCU41_CC42, &SLICE_config);
SLICE_config.timer_concatenation = 1;
XMC_CCU4_SLICE_CompareInit(CCU41_CC43, &SLICE_config);
XMC_CCU4_SLICE_StartTimer(CCU41_CC42);
XMC_CCU4_SLICE_StartTimer(CCU41_CC43);
The following function is used to set the period and duty-cycle (fixed to 50%):
void setPeriod(std::uint32_t period)
{
const uint32_t compare = period/2; //50% PWM
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU41_CC42, static_cast(period & 0xFFFF));
XMC_CCU4_SLICE_SetTimerPeriodMatch(CCU41_CC43, static_cast(period >> 16));
XMC_CCU4_SLICE_SetTimerCompareMatch(CCU41_CC42, static_cast(compare & 0xFFFF));
XMC_CCU4_SLICE_SetTimerCompareMatch(CCU41_CC43, static_cast(compare >> 16));
XMC_CCU4_EnableShadowTransfer(CCU41, XMC_CCU4_SHADOW_TRANSFER_SLICE_2);
XMC_CCU4_EnableShadowTransfer(CCU41, XMC_CCU4_SHADOW_TRANSFER_SLICE_3);
}
This all works fine with a period up to 0xFFFF. Everything above that (more than 16Bit set) deactivates the PWM output. Using the debugger I can see that the timer itself is running and the registers are set correctly. What am I doing wrong?
- Tags:
- IFX
1 Reply
Feb 21, 2018
12:33 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Feb 21, 2018
12:33 PM
Hi Julian,
the thing is that with the timer concatenation you will get 32 bit precision, but the implementation of it is different than what you implemented with splitting the value into lower and upper 16 bits. I would suggest to you to check "CCU4_CONFIG_SLICE_EXAMPLE_XMC47" example. There you will find a working example with attached .pdf that will help you with the understanding of CCU4 concatenation implementation. Additionally, you can find a Python script with an example how to calculate value of compare and period match registers for the both slices.
More or less the calculation of these values can be described with following pseudocode:
and for additional explanation please refer to Reference manual and previously mentioned example.
Best regards,
Deni
the thing is that with the timer concatenation you will get 32 bit precision, but the implementation of it is different than what you implemented with splitting the value into lower and upper 16 bits. I would suggest to you to check "CCU4_CONFIG_SLICE_EXAMPLE_XMC47" example. There you will find a working example with attached .pdf that will help you with the understanding of CCU4 concatenation implementation. Additionally, you can find a Python script with an example how to calculate value of compare and period match registers for the both slices.
More or less the calculation of these values can be described with following pseudocode:
time_interval = 1. / frequency
count = time_interval / tick_resolution
msb = 0;
while True:
count = count / 2
msb = msb + 1
if (count < 65535):
break
higher_period_value = (1 << msb) - 1 <== upper slice period match register value
lower_period_value = int(count) <== lower slice period match register value
temp_period = ((higher_period_value + 1) * (lower_period_value + 1)) + 1
compare_value = ((100 - duty_cycle) * (temp_period)) / 100
lower_compare_value = int(compare_value % lower_period_value) <== lower slice compare match register value
higher_compare_value= int(compare_value / lower_period_value) <== upper slice compare match register value
and for additional explanation please refer to Reference manual and previously mentioned example.
Best regards,
Deni