Skip to main content
GunkutA
Associate III
May 27, 2020
Solved

Prescaler and period values for PWM in STM32

  • May 27, 2020
  • 17 replies
  • 9998 views

I am using STM32F103C8Tx and I am trying to create a PID adjustable PWM. In PID I will be giving values to PWM from 0 to 100 to set the duty cycle. That means my counter period needs to be 100 in Cubemx. Because as I have learnt while I am changing the dutch cycle it changes the counter period. However, I need to create PWM with 200 KHz frequency and the clock of the timer is 72 MHz.In order to achieve a value of 100 in counter period I need to have a 3.6 prescaler. Am I following a wrong way or did I get this PWM duty cycle thing wrong in stm32?

Note: I am changing duty cycle from the code as

htimx.Instance->CCRx =Duty_Cycle;

 I think I cannot put codes as a reply so I will put them here:

static void MX_TIM3_Init(void)
{
 
 /* USER CODE BEGIN TIM3_Init 0 */
 
 /* USER CODE END TIM3_Init 0 */
 
 TIM_MasterConfigTypeDef sMasterConfig = {0};
 TIM_OC_InitTypeDef sConfigOC = {0};
 
 /* USER CODE BEGIN TIM3_Init 1 */
 
 /* USER CODE END TIM3_Init 1 */
 htim3.Instance = TIM3;
 htim3.Init.Prescaler = 1;
 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim3.Init.Period = 359;
 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
 {
 Error_Handler();
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 sConfigOC.OCMode = TIM_OCMODE_PWM1;
 sConfigOC.Pulse = 0;
 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
 if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN TIM3_Init 2 */
 
 /* USER CODE END TIM3_Init 2 */
 HAL_TIM_MspPostInit(&htim3);
 
}
 
 
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
 {
 Error_Handler();
 }
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB;
 PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
 PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }
}

This topic has been closed for replies.
Best answer by berendi

The prescaler value is an integer. Check the timer feature description and register documentation in the reference manual, do not rely on libraries that leave important aspects undocumented.

You can either change the PID algorithm to output a value between 0 and 120 or 360, change the system clock to 60 MHz, or not use the prescaler at all and live with the 0.14 % error.

17 replies

GunkutA
GunkutAAuthor
Associate III
May 27, 2020

I played with prescaler and counter period values. When I tried with higher counter period such as 20000 etc. It gives correct frequency. But when I decrease counter period to 360. It starts to give wrong and higher frequencies. Might be the cause because of the capability of the MCU? Maybe it cannot produce PWM with that high frequency? (200 kHz)

PS: When I use prescaler:1 and counter period:199. Now it works. I guess we cannot use 0 in the prescaler..

waclawek.jan
Super User
May 27, 2020

> But when I decrease counter period to 360. It starts to give wrong and higher frequencies.

Give numbers.

How exactly do you measure it?

 > we cannot use 0 in the prescaler..

Yes we can.

JW