Skip to main content
secures
Associate
September 10, 2020
Solved

PWM Frequency wrong

  • September 10, 2020
  • 3 replies
  • 1908 views

Hi

I'm trying to generate a 64 kHz PWM with 50% dutycycle.

I've configured the SYSCLK to use the HSE in combination with the PLL resulting in 64 MHz. Since I'm using TIM1, which is on APB2, I've configured the APB2 timer clock also to 64 MHz.

However, if I configure TIM1 (no prescalers) to a period of 1000 and a PWM pulse of 500 the generated frequency is not 64 kHz but 32 kHz.

Did I misunderstand something? Where is the additional division by 2 happening?

Thanks

Regards

secures

Clock configuration:

0693W000003RGVuQAO.png

Cube generated code:

void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
 /** Configure the main internal regulator output voltage 
 */
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV8;
 RCC_OscInitStruct.PLL.PLLN = 32;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
 RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
 RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers 
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
 |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_DIV1;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV2;
 RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
 {
 Error_Handler();
 }
 /** Initializes the peripherals clocks 
 */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_USART1
 |RCC_PERIPHCLK_USB;
 PeriphClkInitStruct.PLLSAI1.PLLN = 24;
 PeriphClkInitStruct.PLLSAI1.PLLP = RCC_PLLP_DIV2;
 PeriphClkInitStruct.PLLSAI1.PLLQ = RCC_PLLQ_DIV2;
 PeriphClkInitStruct.PLLSAI1.PLLR = RCC_PLLR_DIV2;
 PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_USBCLK;
 PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
 PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
 PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE0;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN Smps */
 
 /* USER CODE END Smps */
}
 
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 = 1;
 htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim1.Init.Period = 1000;
 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim1.Init.RepetitionCounter = 0;
 htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 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.MasterOutputTrigger2 = TIM_TRGO2_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_ENABLE;
 sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
 sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
 if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
 {
 Error_Handler();
 }
 __HAL_TIM_DISABLE_OCxPRELOAD(&htim1, TIM_CHANNEL_2);
 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();
 }
 /* USER CODE BEGIN TIM1_Init 2 */
 
 /* USER CODE END TIM1_Init 2 */
 HAL_TIM_MspPostInit(&htim1);
 
}

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

To get no prescaler, the prescaler value must be 0 according to the ref man:

"The counter clock frequency (CK_CNT) is equal to F_PSC / (PSC[15:0] + 1)."

3 replies

Nikita91
Nikita91Answer
Lead II
September 10, 2020

To get no prescaler, the prescaler value must be 0 according to the ref man:

"The counter clock frequency (CK_CNT) is equal to F_PSC / (PSC[15:0] + 1)."

secures
securesAuthor
Associate
September 10, 2020

Well that was the missing part. Thanks

TDK
Super User
September 10, 2020

Note also that if you want 1000 ticks per period, you need to set the period to 999.

"If you feel a post has answered your question, please click ""Accept as Solution""."