cancel
Showing results for 
Search instead for 
Did you mean: 

Has anybody converted the PWM frequency and duty cycle measurement exmaple from the STM32CubeMx examples to use STM32CubeMx to configure the hardware (.ioc file to configure the timers)?

Mike Katz
Associate II
Posted on October 10, 2017 at 21:17

The 'STMCubeF2\Projects\STM32F207ZG-Nucleo\Examples\TIM\TIM_PWMInput' example configures the timers with direct calls to the HAL.

I am trying to keep all of the pin allocation and resource initialization within STM32CubMx itself.

Has anyone either created a .ioc file for this or measured frequency and duty cycle using STM32CubeMx to configure the timers?

Thanks in advance.

11 REPLIES 11
Posted on October 11, 2017 at 17:34

Hello!

0690X00000608a1QAA.png

PWM Input mode is selected from the combined channels droplist.

To start the PWM Input , in your main function, call HAL_TIM_PWM_Start (for both channels).

Inside TIM1 settings, the counter period(AR Register) must be higher than PWM period you try to measure.

regards

vf

Posted on October 13, 2017 at 00:25

Thank you for your help.

Do I need to enable the input capture interrupt or the global interrupt for the timer?

Do you have a code sample I might look over or can you point me towards some documentation?

Thanks again.

Posted on October 14, 2017 at 00:08

Hello again.

It is your choice to use interrupts or not, depending  on what you want to do. It is not mandatory.

The initialization code produced from CubeMx.

After Timer initialization in main(.) function, all your code will be

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); 

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);   

Theese functions must de called once to start the PWM input  functionality.

Parse the captured values values by calling

HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);    

HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);

You can call theese functions every time you need to read the captured values.

The User manual for HAL drivers is inside  HAL firmware  at \STM32Cube\Repository\STM32Cube_FW_F2_V1.6.0\Drivers\STM32F2xx_HAL_Driver.

Read also about the IT and DMA versions of HAL_TIM_PWM_Start_IT, HAL_TIM_PWM_Start_DMA. It will helps you to decide the best solution for using timers.

Take a look also inside stm32f2xx_hal_tim.c module. In the begining there is a summary of all tim functions and their use

You can read also

http://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf/jcr:content/translations/en.DM00236305.pdf

Regards

vf

Posted on October 14, 2017 at 17:47

Thank you very much for the help.

What should the setup for the timers be in STM32CubMX?

Posted on October 14, 2017 at 21:45

Hello!

The settings are for the timer as my first's answer figure.

Additionaly, about timer's settings like below

0690X00000608cCQAQ.png

Prescaler value  divides TIM1 clock by PSC+1 and feeds the Counter.

To have the maximum resolution from PWM Input,  AutoReloadRegster Value can be set to 65535 (maximum)  and prescaler can be adjusted, so the maximum counting period of TIM1  to be longer than measurable PWM period.

Example

Want to measure the PWM output from a RC receiver.

Desirable resolution 1 microsecond.

Max period is 20ms

we are not interesting about duty cycle that is between 1 and 2 ms because is allways shorter than period.

TIM1 clock is 120MHZ

Solution: PSC is 119 (120000000Hz /1000000Hz -1) to have 1MHz or 1 microsecond counting period.  And ARR can be above 20000 (20ms),  put 65535.

With theese settings can measure using 1us  resolution, any PWM pulse with period up to 65,5 ms (~15Hz)

Posted on October 21, 2017 at 01:43

I just wanted to say thank you.  I got this working using one of the 32

bit timers running at 60MHz.

The only thing that is surprising is the inaccuracy of about +/- 100Hz

at 38KHz and about +/-3% on the duty cycle.

Thanks again,

          Mike

Moh T.
Associate II
Posted on December 20, 2017 at 16:29

Hi Mike & Vangelis,

am also struggling with setting the PSC values to get pwm output of 28KHz for an IR Led, could you please tell me how did you manage to have the exact values to get 38KHz as an output. I am using stm32f030X, my settings are:

uhPrescalerValue = (uint32_t)(SystemCoreClock / 16000000) - 1;

  __HAL_RCC_TIM3_CLK_ENABLE();

   TimHandle.Instance = TIM3;

   TimHandle.Init.Prescaler         = 1;

   TimHandle.Init.Period            = 200;

   TimHandle.Init.ClockDivision     = 0;

   TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;

   TimHandle.Init.RepetitionCounter = 0;

   TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

I want to use TIM3_CH2 /PA7 to generate a pwm, Thanks a lot in advance.

Moh

Posted on December 20, 2017 at 17:06

The math here is not complicated, the division is integer. Getting 38 KHz cleanly from 16 MHz will be a challenge. What frequency is your STM32F030X running at?

The values for Period and Prescaler are written as N-1 (ie final value comparison)

PWMFreq = (TIMCLK / (Prescaler + 1))  / (Period + 1)

If it is simpler to factor

PWMFreq = TIMCLK / (P * Q)

Prescaler = Q - 1;

Period = P -1;

For 50% duty

Pulse = ((Period + 1) * 100) / 50

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 21, 2017 at 09:36

Hi Clive,

the mcu is STM32F030K6, PWM=38KHZ

SystemCoreClock = 8000000; // 8MHZ with the chip itself runs at 48MHz

So setting so far are like following ?:

♯ define  PERIOD_VALUE       (uint32_t)(666-1)  /* Period Value  */

.

.

.

hPrescalerValue = (uint32_t)(SystemCoreClock / (38000*16)) - 1;

imHandle.Init.Prescaler         = uhPrescalerValue;

TimHandle.Init.Period            = PERIOD_VALUE;

TimHandle.Init.ClockDivision     = 0;

TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;

TimHandle.Init.RepetitionCounter = 0;

TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

.

.

.

/*Configure PWM channel*/

   sConfig.OCMode       = TIM_OCMODE_PWM1;

   sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;

   sConfig.OCFastMode   = TIM_OCFAST_DISABLE;

   sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;

   sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;

   sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;

  /* USER CODE END 2 */

  //sConfig.Pulse = 100;

   sConfig.Pulse = ((PERIOD_VALUE+1)*100)/50; // for 50% duty cycle