2024-09-09 01:29 AM - last edited on 2024-09-09 06:19 AM by SofLit
Hi!
The PWM signals are identical and work as normal except when HAL_TIM_PWM_Stop (or HAL_TIM_PWM_Start) is called at duty 0. The Advanced timer work as expected and cause the output PWM to go low, while both PWM signals go low for the General timer.
I've tried reading the RM0440 Reference manual sections "28 Advanced-control timers (TIM1/TIM8/TIM20)" and "30 General purpose timers (TIM15/TIM16/TIM17)", but has found no clear cause of this.
Below are both my configurations and Oscilloskop output for both control signals and output PWM
Advacned timerTIM8 configuration
__HAL_RCC_TIM8_CLK_ENABLE();
htim8.Instance = TIM8;
htim8.Init.Prescaler = PRESCALER_VALUE;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = HAL_PWM_DEFAULT_PERIOD;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
TIM8->AF2 = 0;
if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
{
// Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig)
!= HAL_OK)
{
// Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1)
!= HAL_OK)
{
// Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0xff;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig)
!= HAL_OK)
{
// Error_Handler();
}
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM8 GPIO Configuration
PC10 ------> TIM8_CH1N PWM_5_CPU
PA15 ------> TIM8_CH1 PWM_6_CPU
*/
HAL_PWM_TIM8_GPIO_ReInit_PWM(FALSE);
HAL_PWM_TIM8_GPIO_ReInit_PWMN(FALSE);
/* Special handling, always keep PWM running, just enable/disable output pin */
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_1);
General timer TIM15 configuration:
__HAL_RCC_TIM15_CLK_ENABLE();
htim15.Instance = TIM15;
htim15.Init.Prescaler = PRESCALER_VALUE;
htim15.Init.Period = HAL_PWM_DEFAULT_PERIOD;
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim15.Init.RepetitionCounter = 0;
htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim15) != HAL_OK)
{
// Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim15, &sMasterConfig)
!= HAL_OK)
{
// Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
/* Use HIGH polarity, different from TIM8 due to the fact that 1 and 1N are swapped for TIM8 vs TIM15:
PC10 ------> TIM8_CH1N PWM_5_CPU
PA15 ------> TIM8_CH1 PWM_6_CPU
PB14 ------> TIM15_CH1 PWM_7_CPU
PB15 ------> TIM15_CH1N PWM_8_CPU
*/
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim15, &sConfigOC, TIM_CHANNEL_1)
!= HAL_OK)
{
// Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0xFF;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim15, &sBreakDeadTimeConfig)
!= HAL_OK)
{
// Error_Handler();
}
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM15 GPIO Configuration
PB14 ------> TIM15_CH1 PWM_7_CPU
PB15 ------> TIM15_CH1N PWM_8_CPU
*/
HAL_PWM_TIM15_GPIO_ReInit_PWM(FALSE);
HAL_PWM_TIM15_GPIO_ReInit_PWMN(FALSE);
/* Special handling, always keep PWM running, just enable/disable output pin */
HAL_TIM_PWM_Start(&htim15, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim15, TIM_CHANNEL_1);
This is both PWM signals at 50% duty, and work as intended
This is the Advanced timer at 0% duty, and as expected the output is now 0 with 1 signals hight and 1 low
This is the General timer at duty 0%
Solved! Go to Solution.
2024-09-15 11:13 PM
After much further examination, I have concluded that controlling the PB15 (Green) signal manually at duty zero instead will be easier, as I still have not figured out why the timers work differently after many days.
2024-09-09 02:20 AM
On those pictures, green and blue are the two complementary outputs, correct? And what is the purple one?
Read out and compare/post TIM registers content for the two timers (and perhaps also the relevant GPIO registers content).
JW
2024-09-09 02:21 AM
Maybe try another value for idle mode(s):
/** @defgroup TIM_Output_Compare_Idle_State TIM Output Compare Idle State
* @{
*/
#define TIM_OCIDLESTATE_SET TIM_CR2_OIS1 /*!< Output Idle state: OCx=1 when MOE=0 */
#define TIM_OCIDLESTATE_RESET 0x00000000U /*!< Output Idle state: OCx=0 when MOE=0 */
/**
* @}
*/
/** @defgroup TIM_Output_Compare_N_Idle_State TIM Complementary Output Compare Idle State
* @{
*/
#define TIM_OCNIDLESTATE_SET TIM_CR2_OIS1N /*!< Complementary output Idle state: OCxN=1 when MOE=0 */
#define TIM_OCNIDLESTATE_RESET 0x00000000U /*!< Complementary output Idle state: OCxN=0 when MOE=0 */
/**
* @}
*/
2024-09-09 06:12 AM
The purple one is an output controlled by the two complementary outputs depending on their duty.
2024-09-09 06:54 AM
Thanks.
I was more interested in the registers content, though.
JW
2024-09-15 11:13 PM
After much further examination, I have concluded that controlling the PB15 (Green) signal manually at duty zero instead will be easier, as I still have not figured out why the timers work differently after many days.
2024-09-15 11:56 PM
That is not a solution (remove that mark). Its a different approach. Also you still might have a problem, that will come back one day and haunt you!