2

I can't seem to get TIM8 PWM to work with anything that I try. I've tried all timers and they all work with my PWM driver, except TIM8. All timers are generated with CubeMx and there are no conflicts.

Here are some snipits of the code. The driver is fairly large so I cut out parts of it:

Pin config:

//Tim 8 Chan 1 IN1A
GPIO_InitStructure.Pin          = GPIO_PIN_6;
GPIO_InitStructure.Mode         = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull         = GPIO_NOPULL;
GPIO_InitStructure.Speed        = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate    = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

//Tim 8 Chan 2 IN1B
GPIO_InitStructure.Pin          = GPIO_PIN_7;
GPIO_InitStructure.Mode         = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull         = GPIO_NOPULL;
GPIO_InitStructure.Speed        = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate    = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

//Tim 8 Chan 3 IN2A
GPIO_InitStructure.Pin          = GPIO_PIN_8;
GPIO_InitStructure.Mode         = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull         = GPIO_NOPULL;
GPIO_InitStructure.Speed        = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate    = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

//Tim 8 Chan 4 IN2B
GPIO_InitStructure.Pin          = GPIO_PIN_9;
GPIO_InitStructure.Mode         = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull         = GPIO_NOPULL;
GPIO_InitStructure.Speed        = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate    = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

Timer setup:

static PWM_ERC_T Timer8_Init(PWM_HANDLE_T *pwmHandle_, uint16_t prescaler_, uint16_t period_, uint16_t pulse_)
{

PWM_ERC_T erc = PWM_ERC_NO_ERROR;

__TIM8_CLK_ENABLE();

pwmHandle_->TimerHandle.Instance = TIM8;

TIM_MasterConfigTypeDef masterConfig;
TIM_BreakDeadTimeConfigTypeDef breakDeadTimeConfig;
TIM_OC_InitTypeDef configOC;

pwmHandle_->TimerHandle.Init.Prescaler          = prescaler_;
pwmHandle_->TimerHandle.Init.CounterMode        = TIM_COUNTERMODE_UP;
pwmHandle_->TimerHandle.Init.Period             = period_;
pwmHandle_->TimerHandle.Init.ClockDivision      = TIM_CLOCKDIVISION_DIV1;
pwmHandle_->TimerHandle.Init.RepetitionCounter  = 0;
HAL_TIM_PWM_Init(&pwmHandle_->TimerHandle);

masterConfig.MasterOutputTrigger    = TIM_TRGO_RESET;
masterConfig.MasterOutputTrigger2   = TIM_TRGO2_RESET;
masterConfig.MasterSlaveMode        = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&pwmHandle_->TimerHandle, &masterConfig);

breakDeadTimeConfig.OffStateRunMode     = TIM_OSSR_DISABLE;
breakDeadTimeConfig.OffStateIDLEMode    = TIM_OSSI_DISABLE;
breakDeadTimeConfig.LockLevel           = TIM_LOCKLEVEL_OFF;
breakDeadTimeConfig.DeadTime            = 0;
breakDeadTimeConfig.BreakState          = TIM_BREAK_DISABLE;
breakDeadTimeConfig.BreakPolarity       = TIM_BREAKPOLARITY_HIGH;
breakDeadTimeConfig.BreakFilter         = 0;
breakDeadTimeConfig.Break2State         = TIM_BREAK2_DISABLE;
breakDeadTimeConfig.Break2Polarity      = TIM_BREAK2POLARITY_HIGH;
breakDeadTimeConfig.Break2Filter        = 0;
breakDeadTimeConfig.AutomaticOutput     = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&pwmHandle_->TimerHandle, &breakDeadTimeConfig);

configOC.OCMode         = TIM_OCMODE_PWM1;
configOC.Pulse          = pulse_;
configOC.OCPolarity     = TIM_OCPOLARITY_HIGH;
configOC.OCNPolarity    = TIM_OCNPOLARITY_HIGH;
configOC.OCFastMode     = TIM_OCFAST_DISABLE;
configOC.OCIdleState    = TIM_OCIDLESTATE_RESET;
configOC.OCNIdleState   = TIM_OCNIDLESTATE_RESET;

if(pwmHandle_->Init.Channels & PWM_CHANNEL_1)
{
    HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);
}

if(pwmHandle_->Init.Channels & PWM_CHANNEL_2)
{
    HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_2);
}

if(pwmHandle_->Init.Channels & PWM_CHANNEL_3)
{
    HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_3);
}

if(pwmHandle_->Init.Channels & PWM_CHANNEL_4)
{
    HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_4);
}

I assure you each of the channels are being enabled and the prescaller/period and period are being calculated correctly.

Any thoughts? This is the only timer that has issues.

Solution:

Finally figured out what was wrong.

HAL_TIM_OC_Init(&pwmHandle_->TimerHandle); 

has to be added for TIM8 for some reason... not sure why and

HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1); 

needs to be used instead of

HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);

Correct Timer Setup:

static PWM_ERC_T Timer8_Init(PWM_HANDLE_T *pwmHandle_, uint16_t prescaler_, uint16_t period_, uint16_t pulse_)
{

PWM_ERC_T erc = PWM_ERC_NO_ERROR;


TIM_MasterConfigTypeDef masterConfig;
TIM_BreakDeadTimeConfigTypeDef breakDeadTimeConfig;
TIM_OC_InitTypeDef configOC;

pwmHandle_->TimerHandle.Init.Prescaler          = prescaler_;
pwmHandle_->TimerHandle.Init.CounterMode        = TIM_COUNTERMODE_UP;
pwmHandle_->TimerHandle.Init.Period             = period_;
pwmHandle_->TimerHandle.Init.ClockDivision      = TIM_CLOCKDIVISION_DIV1;
pwmHandle_->TimerHandle.Init.RepetitionCounter  = 0;
HAL_TIM_OC_Init(&pwmHandle_->TimerHandle);
HAL_TIM_PWM_Init(&pwmHandle_->TimerHandle);

masterConfig.MasterOutputTrigger    = TIM_TRGO_RESET;
masterConfig.MasterOutputTrigger2   = TIM_TRGO2_RESET;
masterConfig.MasterSlaveMode        = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&pwmHandle_->TimerHandle, &masterConfig);

breakDeadTimeConfig.OffStateRunMode     = TIM_OSSR_DISABLE;
breakDeadTimeConfig.OffStateIDLEMode    = TIM_OSSI_DISABLE;
breakDeadTimeConfig.LockLevel           = TIM_LOCKLEVEL_OFF;
breakDeadTimeConfig.DeadTime            = 0;
breakDeadTimeConfig.BreakState          = TIM_BREAK_DISABLE;
breakDeadTimeConfig.BreakPolarity       = TIM_BREAKPOLARITY_HIGH;
breakDeadTimeConfig.BreakFilter         = 0;
breakDeadTimeConfig.Break2State         = TIM_BREAK2_DISABLE;
breakDeadTimeConfig.Break2Polarity      = TIM_BREAK2POLARITY_HIGH;
breakDeadTimeConfig.Break2Filter        = 0;
breakDeadTimeConfig.AutomaticOutput     = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&pwmHandle_->TimerHandle, &breakDeadTimeConfig);

configOC.OCMode         = TIM_OCMODE_PWM1;
configOC.Pulse          = pulse_;
configOC.OCPolarity     = TIM_OCPOLARITY_HIGH;
configOC.OCNPolarity    = TIM_OCNPOLARITY_HIGH;
configOC.OCFastMode     = TIM_OCFAST_DISABLE;
configOC.OCIdleState    = TIM_OCIDLESTATE_RESET;
configOC.OCNIdleState   = TIM_OCNIDLESTATE_RESET;

if(pwmHandle_->Init.Channels & PWM_CHANNEL_1)
{
    HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);
}

if(pwmHandle_->Init.Channels & PWM_CHANNEL_2)
{
    HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_2);
}

if(pwmHandle_->Init.Channels & PWM_CHANNEL_3)
{
    HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_3);
}

if(pwmHandle_->Init.Channels & PWM_CHANNEL_4)
{
    HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_4);
}

return erc;

}

user2654735
  • 323
  • 5
  • 19
  • Configuration of any STM32 timer (TIM1 and TIM8 included) directly on registers takes 10 lines of code max... This HAL/SPL nonsense is completely ridiculous... – Freddie Chopin Jan 08 '17 at 20:45
  • I don't see enabling the Peripherals clock when initializing the pins. there should be a call of the function `RCC_AHBPeriphClockCmd()` to initialize the Peripherals clock. – gmug Jan 09 '17 at 10:53
  • Did you resolve this? I am having the same issue on the same timer , although I have configured it via the LL library. – Clifford Jun 30 '22 at 17:56

1 Answers1

0

TIM1 and TIM8 have a bit MOE (Main Output Enable) in the TIMx_BDTR register that is unique to these timers. The PWM is not output unless that bit is set to 1.

Clifford
  • 88,407
  • 13
  • 85
  • 165