cancel
Showing results for 
Search instead for 
Did you mean: 

PWM stop state problem - I want to instantaneously stop a complimentary PWM in a low state F042, timer1

DMolo
Senior

I want to generate bursts of complimetary PWM to drive a half bridge. I have the PWM working fine, with deatime etc... but when I call:

HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_1);

HAL_TIMEx_PWMN_Stop(&htim1,TIM_CHANNEL_1);

Rather than stopping to a defined state, it goes to (I think) reset state and drifts down to 0V. I want it to pull both lines LOW when I stop the PWM, so that the Half-Bridge goes to floating.

0690X0000089w70QAA.jpg

Timer init code is:

static void MX_TIM1_Init(void)
{
 
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
 
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 256;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500;
  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(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sConfigOC.Pulse = 0;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 5;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  HAL_TIM_MspPostInit(&htim1);
 
}

5 REPLIES 5
S.Ma
Principal

How about turn the output as output GPIO with low level?

Or short the output with another GPIO which is open drain and force a low level whenever needed?

DMolo
Senior

These would both potentially work, but turning the output to GPIO involves resetting all the pinstates and re-running the init funcitons (slow, tedious...surely there's a better way?)

Shorting the output with a GPIO 1) uses extra GPIO and 2) 1 messup and your chip is dead.

On the Atmel chips (for example) there is a bitmask where you can just write enable alternative function and otherwise it just goes to the state as if the timer was not running PWM.

I tried initialising the pins as GPIO and writing low before initialising the timer, but no luck. As soon as you init the timer PWM, the old GPIO init is essentially dead...

DMolo
Senior

De-initialising the timer is also not an option, I need to keep the other channels running PWM.

> On the Atmel chips (for example) there is a bitmask where you can just write enable alternative function and otherwise it just goes to the state as if the timer was not running PWM.

It's the same in STM32, if you ditch Cube and read the reference manual (GPIOx_MODER).

JW

DMolo
Senior

OK,

So, init()ing as GPIO, then writing GPIO on PA7 and 8 low... Then init()ing timer, then in while(1) loop I put:

HAL_Delay(1);
GPIOA->MODER &= ~0b00000000000000111100000000000000;
GPIOA->MODER |=  0b00000000000000010100000000000000;
 
HAL_Delay(1);
GPIOA->MODER &= ~0b00000000000000010100000000000000;
GPIOA->MODER |=  0b00000000000000101000000000000000;

I get the desired effect. I think this should scale to the other GPIOs/timer channels.

Cheers Jan!