3
\$\begingroup\$

I have a STM32F429 Discovery and wants set a PWM to toggle led with period of 1 second using Timer 1, channel 1.

So, I follow this equation:

enter image description here

My clock APB1 is set to 1MHz.

So by my calculations I got a value for the Prescaler = 19.

PWM_Frequency = 1Hz;
Timer_Clock = 1MHz;
Timer_Count = 49999;
RCR = 0;

And for the pulse 50% I use:

pulse_length = ((TIM_Period + 1) * DutyCycle) / 100 - 1;
pulse_lenght = 24999;

enter image description here

But not works, the Led blinks very faster.

Follow my code:

static void MX_TIM1_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 19;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 49999;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  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.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 24999;
  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(__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.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_TIM_MspPostInit(&htim1);

}
\$\endgroup\$
4
  • \$\begingroup\$ if you want led to toggle every 1s the PWM frequency should be 0.5Hz an ratio 50% \$\endgroup\$ Aug 20, 2017 at 22:39
  • \$\begingroup\$ What is Ratio? I'am brazilian. So I calculate with 0.5Hz and find Prescaler = 39. I don't have oscilloscopie and the led not appers toggling with 1 sec. \$\endgroup\$ Aug 20, 2017 at 23:10
  • \$\begingroup\$ ????? PWM RATIO.Google it. If the frequency is different that means your clock does not have 1MHz frequency \$\endgroup\$ Aug 20, 2017 at 23:17
  • \$\begingroup\$ Ok, I unterstand more my problem, my question is: The clock source of TIMER1 is APB1 or APB2? \$\endgroup\$ Aug 21, 2017 at 19:11

1 Answer 1

1
\$\begingroup\$

Ratio is razão. The amount of time ON over the total PWM period. 50% ratio is ON half of the time. 1Hz@50% = 0.5s ON - 0.5s OFF, 1Hz@30% = 0.3s ON - 0.7s OFF.

So if your TIM1 output clock is really 1Hz the LED gonna change state every 0.5s.

If you go to page 211 of the datasheet you can see that TIM1 is driven by APB2 (RCC_APB2ENR). On page 517 you can see that the pulse clock for TIM1 is derived from CK_INT that, on slave mode OFF, comes from the APB2 clock.

The TIMx clocks can be either x1 or x2 the APBx clock, it depends on the APBx prescaler (x2 if APBx prescaler is not /1). If you are using STM32Cube you can see the prescaler value on the Clock Tab, otherwise search your code for SystemClock_Config() and you can find the prescaler for APB2 searching for the following line:

static void SystemClock_Config(void){
  (...)
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  (...)
}

In the example above APB2 prescaler is /2. So, let's assume that the PLL clock output is 180MHz (the maximum clock for your MCU), the APB2 clock gonna be 90MHz, for TIMx that's doubled, as prescaler is greater than /1. Therefore, on your code that would mean:

TIM1_INPUT_CLK = 180MHz;
TIM1_PSC = 19;
TIM1_PSC_OUTPUT_CLK = 180MHz / (19 + 1) = 9MHz;
TIM1_CNT = 49999;
TIM1_PERIOD_CLK = 9MHz / (49999 + 1) = 180Hz;

Using your values your PWM period would be one millionth of your PLL output clock. Are you sure that your system clock is 1MHz? Seems rather low. You can check that value on STM32Cube. Or find this snippet on your code:

static void SystemClock_Config(void){
  (...)
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = Xm;
  RCC_OscInitStruct.PLL.PLLN = Xn;
  RCC_OscInitStruct.PLL.PLLP = Xp;
  (...)
}

Where SYSCLK = ((Crystal / Xm) * Xn) / Xp)

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.