cancel
Showing results for 
Search instead for 
Did you mean: 

Problem using 3 Output Compare Channels for Center Aligned PWM

SKokk.1
Associate II

Hello,

i am using the STM32F103C6 MCU and i would like to produce 3 different Center Aligned PWM signals with 16KHz frequency and Duty Cycle 1 to 99%. I would like to change the duty cycle on fly using the CCR registers.

I am configuring the 3 of TIM1's channels as Output Compare:

0693W000000W0o7QAC.png

Then i choose the Center Aligned_3 mode and setting the frequency on 16KHz (frequency is correct):

0693W000000W0o8QAC.png

Finally, every channel has the same settings as below:

0693W000000W0phQAC.png

With CubeMX's default code, i am just starting the OC and setting the desired pulse:

/* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
 
  /* USER CODE BEGIN 2 */
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_3);
 
  TIM1->CCR1 = 400;    //Channel_1 ~ 82% Duty Cycle
  TIM1->CCR2 = 1125;  //Channel_2 ~ 50% Duty Cycle
  TIM1->CCR3 = 2200;  //Channel_3 ~ 2% Duty Cycle

And on simulator everything is correct:

0693W000000W0sWQAS.png

If we change the CCR1 to lower value:

TIM1->CCR1 = 100;  //Channel_1 95% Duty Cycle

Seems like Channel 1 is not aligned with the others, like it is shifted:

0693W000000W0uDQAS.png

  • Can someone help me and explain me what i am doing wrong?
  • Is there any other way to produce those Center Aligned PWM signals?
  • What is the safest way to change duty cycle on fly? Should i use the compare IRQ?
6 REPLIES 6
Svish.2
Associate II

Firstly you can directly use the "PWM Generation CHx" option from the CubeMx dropdown for each channel. This will readily give you the PWM depending on the pulse and period values. I used the same to generate 3 output PWMs for my motor project.

Thanks

SKokk.1
Associate II

Yeah, its about motor project and SVM.

I will try your suggestion.

SKokk.1
Associate II

Now i am using the "PWM Generation CHx" option but i am still facing issues with the alignment.

With the below settings:

static void MX_TIM1_Init(void)
{
 
  /* USER CODE BEGIN TIM1_Init 0 */
 
  /* USER CODE END TIM1_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
 
  /* USER CODE BEGIN TIM1_Init 1 */
 
  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
  htim1.Init.Period = 2250-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 100;
  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();
  }
  sConfigOC.Pulse = 500;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.Pulse = 700;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  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.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */
 
  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);
 
}

The output looks like this:

0693W000000W1cPQAS.png

SKokk.1
Associate II

I have done similar projects with 8bit MCU from other manufacturer, as i remember there were some limitations on duty cycle on center aligned PWM (could not go to 0% or 100% - you had to select).

So there is the same issue here, a cube bug or what? Could someone help?

Try on real hardware.

JW

SKokk.1
Associate II

Due to quarantine, i have not access to oscilloscope. That's why i am using simulator.

I don't think the problem is Proteus-Simulator.