Prescaler and period values for PWM in STM32
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-26 11:54 PM
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();
}
}
Solved! Go to Solution.
- Labels:
-
STM32CubeMX
-
STM32F1 Series
-
TIM
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 12:51 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 12:51 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 1:01 AM
I guess the easiest way to change PID output to 0 and 360 range. Set Prescaler to 2 and Counter Period to 179. So it will give me 200 kHz PWM while using 72 MHz clock. However, since program adds +1 to counter period. I will never have a %0 duty cycle. Is that correct?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 1:06 AM
> However, since program adds +1 to counter period. I will never have a %0 duty cycle. Is that correct?
No.
If CCRx = 0, you have 0% duty cycle; if CCR = ARR CCR > ARR you have 100% duty cycle (depending on the particular PWM mode you are using, this may be the other way round).
Read the TIM chapter in RM.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 1:24 AM
Reference manual, TIMx capture/compare mode register 1 (TIMx_CCMR1) description:
110: PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT<TIMx_CCR1 else inactive.
When you want a counter period of 100 cycles, you set ARR = 99. CNT counts from 0 to 99, then starts again at 0.
To have 0% duty cycle, set CCR1 = 0. Because CNT can't be less than 0, the output is always inactive.
To have 100% duty cycle, set CCR1 = 100. Now CNT is always less than CCR1, because CNT is always in the 0..99 range, so the output is always active.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 4:37 AM
Now eventhough APB1 Timer Clock is 72 MHz. Prescaler is 0 and Counter Period is 359. The frequency of the PWM is 12 Hz. I use blue pill STM32. What might be the cause . I know it is a little bit irrelevant from the topic but I didn't want to open a new topic for that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 4:50 AM
Please post the contents of the RCC and timer registers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 5:02 AM
> The frequency of the PWM is 12 Hz
How do you know?
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 5:04 AM
Here they are from CubeMX
RCC
Clock Config Screen
Timer 3
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-05-27 5:10 AM
No, the contents of the hardware registers. Cube screenshots and and source code containing HAL function calls are useless for troubleshooting.
