cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L1 Discovery Kit 5MHz PWM Generation

Arthur Franca
Associate II
Posted on March 06, 2018 at 17:49

Hello,

I have been using the STM32L1 Discovery Kit with the STM32L152RCT6 MCU. 

A project that I am working on requires me to output two PWM signals. One of these is a 100KHz square wave and the other is 5MHz square wave. 

I have gotten the 100KHz wave to work correctly, however I am unable to generate a 5MHz pwm from my board. I am using Timers 4 and 11 currently to generate these two signals and the code is as follows:

/* TIM3 init function */

static void MX_TIM3_Init(void)

{

TIM_ClockConfigTypeDef sClockSourceConfig;

TIM_MasterConfigTypeDef sMasterConfig;

TIM_OC_InitTypeDef sConfigOC;

htim3.Instance = TIM3;

htim3.Init.Prescaler = 2;

htim3.Init.CounterMode = TIM_COUNTERMODE_UP;

htim3.Init.Period = 2;

htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_Base_Init(&htim3) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sConfigOC.OCMode = TIM_OCMODE_PWM1;

sConfigOC.Pulse = 1;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

HAL_TIM_MspPostInit(&htim3);

}

/* TIM4 init function */

static void MX_TIM4_Init(void)

{

TIM_ClockConfigTypeDef sClockSourceConfig;

TIM_MasterConfigTypeDef sMasterConfig;

TIM_OC_InitTypeDef sConfigOC;

htim4.Instance = TIM4;

htim4.Init.Prescaler = 106;

htim4.Init.CounterMode = TIM_COUNTERMODE_UP;

htim4.Init.Period = 2;

htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_Base_Init(&htim4) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sConfigOC.OCMode = TIM_OCMODE_PWM1;

sConfigOC.Pulse = 1;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

HAL_TIM_MspPostInit(&htim4);

}

/* TIM11 init function */

static void MX_TIM11_Init(void)

{

TIM_ClockConfigTypeDef sClockSourceConfig;

TIM_OC_InitTypeDef sConfigOC;

htim11.Instance = TIM11;

htim11.Init.Prescaler = 2;

htim11.Init.CounterMode = TIM_COUNTERMODE_UP;

htim11.Init.Period = 2;

htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_Base_Init(&htim11) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

if (HAL_TIM_ConfigClockSource(&htim11, &sClockSourceConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

if (HAL_TIM_PWM_Init(&htim11) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sConfigOC.OCMode = TIM_OCMODE_PWM1;

sConfigOC.Pulse = 1;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

if (HAL_TIM_PWM_ConfigChannel(&htim11, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

HAL_TIM_MspPostInit(&htim11);

}

When I run my board with this code I find that the TIM4 correctly ouputs a 100KHz square wave with a peak to peak voltage of 3V. The TIM11 channel outputs an unclean square wave with a very low peak to peak voltage and only approx. a 3.5MHz signal. If I try to reduce the prescaler value to 1 in order to increase the frequency further, I lose the waveform completely. The results from the oscilliscope are show below:

TIM4 -

0690X00000609xaQAA.png

TIM11 -

0690X00000609xQQAQ.png

Any help on getting the TIM11 pwm to be a clean square at 5MHz with 3V peak to peak would be greatly appreciated.

Thanks,

Arthur

#tim-pwm #stm32l152
22 REPLIES 22
Arthur Franca
Associate II
Posted on March 07, 2018 at 17:54

I have now corrected the speed setting on the pin by putting it to a high setting. 

I then kept my period value at 2 with a pulse of 1 for a 50% duty cycle. My prescaler value I tried placing at 1. This would in theory give me my approx. desired frequency according to this equation I found online:

   Desired Freq = MCU Freq. / ([Prescaler +1][Period+1])

   5.3333MHz = 32MHz / ([1+1][2+1])

Upon testing this I found that I still had a similar issue:

- With prescaler set to 1 there is no output at all

- As I increase the prescaler value I get an output at a low amplitude with the expected frequency until approx. a prescaler value of 9 where I get a full 3V peak to peak clean square wave

I have checked my oscilloscope rating and it samples up 100MHz so there should be no problem there.

Posted on March 07, 2018 at 17:58

I forgot that, I am using Cube only for pins mapping, because Cube is not working with arduino IDE.

High - it is sound nice, but they not say how much is it in numbers.

Posted on March 07, 2018 at 18:16

5.3333MHz = 32MHz / ([2+1])

I don't know how this formula is working, it is look strange '([2+1])'

, replace it by x, for 6 and you have your 5.3333. if x is not an integer you have no signal at the output.

Posted on March 07, 2018 at 18:25

Hi Ted,

Sorry the high setting did work! It was a weird coding issue I've now fixed.

The denominator in the formula is [1+1][2+1] = 2*3 = 6

I now am getting the 5.3MHz wave. however I am also getting a significant amount of noise on both timer channels now:

https://scontent-sea1-1.xx.fbcdn.net/v/t0-12/28722352_10216521141648890_1114448581_n.jpg?oh=f8ad7d451adf8ae0b98773e573e427a9&oe=5AA1F719

Zooming in closer:

https://scontent-sea1-1.xx.fbcdn.net/v/t0-12/28741184_10216521141688891_1889000873_n.jpg?oh=95db2874d583d607edd04974cadcf1a1&oe=5AA2F13E

Posted on March 07, 2018 at 18:43

With prescaler set to 1 there is no output at all - That's why I said is strange.

For noise use RC filter, try 10k resistor and 1nF capacitor.

https://www.google.ca/search?q=rc+filter&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjc-_ii4drZAhUo_IMKHQ3rD2IQ_AUICigB&biw=1440&bih=787&sharpimgrc=qIRKr8nEbS5HwM:

ted korczak
Associate III
Posted on March 07, 2018 at 19:46

If you have - Alternate Function Push Pull - nothing more can be done - my opinion

Posted on March 07, 2018 at 18:52

No no, that was my original mistake the above code is now working with prescaler value at 1!

RC filter would definitely do it. Is there no way to clean the wave further on the MCU though?

Posted on March 07, 2018 at 19:07

Zoom in pic - I see 5 pulses should be 6, you are dividing by 6, maybe if you use div/V scale 0.1 instead 5/V you can find missing pulse.

Any way I don't think that you can have a nice squarwe withouth filter in your case, for stm 32f 103 looks much better, MCU 72MHz = more samples per cycle.

Posted on March 07, 2018 at 19:23

Yes you were right my division was a bit off, I have now corrected. 

And yes that makes sense. Thank for your help!

Posted on March 08, 2018 at 00:06

Common noise is indicating the earth line to your probes is too long.

earth each probe as close to the uP gnd cap pin as you can get.