1
\$\begingroup\$

I have problems using the complementary PWM feature of the STM32-L432KC. The non-complemementary pin ch1 is generating the right signal, but the ch1n pin is always at GND.

I want to use channel 1,2 and 3 on Timer 1, optimally only the inverse channel, as far as i can see this should be possible. For testing is have also enabled the ch1 which is working.

I have configured the HAL using CubeMx, my initialisation code is:

void MX_TIM1_Init(void)
{

  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 80;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 20000;
  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.MasterOutputTrigger2 = TIM_TRGO2_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 = 1000;
  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__);
  }

  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 = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim1);

}

Is there anything configured incorrectly? Is it possible to only use the inverse channel?

I start the timer by calling:

HAL_TIM_Base_Start(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
\$\endgroup\$
5
  • \$\begingroup\$ HAL. Who knows what is there. Why don't you configure the registers directly instead? \$\endgroup\$ Commented Feb 4, 2018 at 10:06
  • \$\begingroup\$ I would love to configure everything by myself but i need to configure a lot of peripherals (I²C with DMA, UART, SPI...) and i don't have the time to do it all by hand. \$\endgroup\$
    – aul12
    Commented Feb 4, 2018 at 10:48
  • 1
    \$\begingroup\$ And what is the problem? It is quicker than the HAL bloatware. Now you will waste days asking for the elementary stuff. Usually HAL takes much more time than the bare register approach. This "time saving" is a legend. Now you wasted 5 hours. Your problem is sortable in 3 minutes without the HAL \$\endgroup\$ Commented Feb 4, 2018 at 12:44
  • \$\begingroup\$ Can you show your PWM Start calls as well? \$\endgroup\$
    – Catsunami
    Commented Feb 8, 2018 at 16:27
  • \$\begingroup\$ I added the initialization code to my original question \$\endgroup\$
    – aul12
    Commented Feb 16, 2018 at 15:45

2 Answers 2

5
\$\begingroup\$

you haven't started the NChannels. do it like this:

   HAL_TIM_MspPostInit(&htim1);


   /* Start channels x*/

   if(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
   {
     /* Starting Error*/
     Error_Handler();
   }
   /* Start channel xN*/
   if(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
   {
    /*Starting Error*/
     Error_Handler();
   }

   if(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
   {
     /* Starting Error*/
     Error_Handler();
   }
   /* Start channel xN*/
   if(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
   {
    /*Starting Error*/
     Error_Handler();
   }

   if(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
   {
     /* Starting Error*/
     Error_Handler();
   }
   /* Start channel xN*/
   if(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
   {
    /*Starting Error*/
     Error_Handler();
   }
\$\endgroup\$
0
\$\begingroup\$

When you call HAL_TIM_PWM_Init function it calls HAL_TIM_PWM_MspInit that commonly placed in stm32...._hal_msp.c in project sources. There is initialization of GPIO for working timers peripheral. Something like this

  GPIO_InitStruct.Pin = TIM_LED_GPIO_PIN_CHANNEL1;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = TIM_LED_GPIO_AF;
  HAL_GPIO_Init(TIM_LED_GPIO_CHANNEL1_PORT, &GPIO_InitStruct);

So possibly you have no init there?

\$\endgroup\$
2
  • \$\begingroup\$ I have the init function (in my code it is in the tim.c file), but my initialization parameters are slightly different: the Pull parameter is set to GPIO_NOPULL, and the Speed paramter to GPIO_SPEED_FREQ_LOW but for the working ports the parameter are the same \$\endgroup\$
    – aul12
    Commented Feb 16, 2018 at 15:53
  • \$\begingroup\$ May you show full code here for both ports? \$\endgroup\$ Commented Feb 20, 2018 at 3:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.