1

I'm currently working myself into STM32 programming for a project. For this project I need to produce a 20kHz (=f_pwm) center-aligned PWM. Using CubeMX I set the TIM1 clk to 144 MHz (=f_tim) by using the PLLCLK*2. Then I proceeded by setting the ARR register to period=f_tim/(2*f_pwm). The *2 is from the center-aligned mode, since it counts up and down. After programming the STM32 with those parameters, I'm only getting 10 kHz (measured on a scope). My calculation and the clock settings seem to be correct (checked through the generated code and written registers as well), so I'm out of ideas now. Did anybody already encounter such a problem or knows what the cause might be? Apprehended find my CubeMX clock config and the corresponding code parts.

Thanks to everyone having a look into it!

CubeMX clock config

System Clock Config:

 void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct;
 RCC_ClkInitTypeDef RCC_ClkInitStruct;
 RCC_PeriphCLKInitTypeDef PeriphClkInit;
 /**Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSICalibrationValue = 16;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
 RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 /**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(__FILE__, __LINE__);
 }
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3|RCC_PERIPHCLK_TIM1
 |RCC_PERIPHCLK_ADC12|RCC_PERIPHCLK_ADC34
 |RCC_PERIPHCLK_TIM20;
 PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_PCLK1;
 PeriphClkInit.Adc12ClockSelection = RCC_ADC12PLLCLK_DIV64;
 PeriphClkInit.Adc34ClockSelection = RCC_ADC34PLLCLK_DIV64;
 PeriphClkInit.Tim1ClockSelection = RCC_TIM1CLK_PLLCLK;
 PeriphClkInit.Tim20ClockSelection = RCC_TIM20CLK_PLLCLK;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 /**Configure the Systick interrupt time 
 */
 HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
 /**Configure the Systick 
 */
 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
 /* SysTick_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

TIM1 Init:

void MX_TIM1_Init(void)
{
 TIM_ClockConfigTypeDef sClockSourceConfig;
 TIM_MasterConfigTypeDef sMasterConfig;
 TIM_OC_InitTypeDef sConfigOC;
 TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
 htim1.Instance = TIM1;
 htim1.Init.Prescaler = 1;
 htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
 htim1.Init.Period = 3600;
 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(__FILE__, __LINE__);
 }
 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
 if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 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 = 0;
 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_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);
}

Set CCR and start PWM:

//Sets TIM_CCR (Compares to counter value), From _hal_tim_ex.h:921
 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,1800);
 //Start PWM
 HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_3);
glts
23k12 gold badges80 silver badges94 bronze badges
asked Jun 4, 2018 at 13:38
3
  • Just solved it myself: I had the Prescaler set to 1 (well, f_tim/1 = f_tim, right?). After setting it to 0 I got the desired f_pwm. From that I'll assume that a prescale of 0 gives the actual PLLCLK*2 and a prescaler >0 gives a timer clock derived fro PLLCLK (which is also SYSCLK). Thanks anyways to anyone who might've invested his time into this problem! Commented Jun 4, 2018 at 13:55
  • Another comment: Checked the corresponding register PSC in the datasheet and found this one: fCK_PSC / (PSC[15:0] + 1). Kind of interesting, that the actual prescale is the set value+1. Commented Jun 4, 2018 at 14:03
  • You might want to formulate an answer and accept it to help other people find the solutions for their problems easier :) Commented Jun 5, 2018 at 6:45

1 Answer 1

3

Just solved it myself: I had the Prescaler (Register TIMx_PSC) set to 1 (logically thinking, f_tim/1 = f_tim, right?). After setting it to 0 I got the desired f_pwm. I then digged into my STM's data sheet and found out, that f_tim is calculated as follows: f_tim = f_clk / (PSC+1). Therefore: Prescale set to 0 gives a prescale of 1, set to 1 gives 2 etc.

answered Jun 5, 2018 at 8:10
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.