cancel
Showing results for 
Search instead for 
Did you mean: 

Example: PWM on STM32-Discovery Blue LED

Posted on February 12, 2011 at 21:39

Hey,

I just spent a bunch of time sorting out how to get the darn PWM output on the blue LED on the STM32-Discovery board.  After a lot of time pouring over the datasheets and forum posts I was finally able to work out the following code.  Seems to work very well.

    RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |

            RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |

            RCC_APB2Periph_AFIO, ENABLE );

 

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );

 

    // Set the Vector Table base address at 0x08000000.

    NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );

 

    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );

 

    // Configure HCLK clock as SysTick clock source.

    SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );

    // Setup Blue LED on STM32-Discovery Board to use PWM.

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            // Alt Function - Push Pull

    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_PinRemapConfig( GPIO_FullRemap_TIM3, ENABLE );        // Map TIM3_CH3 to GPIOC.Pin8

 

    // Let PWM frequency equal 100Hz.

    // Let period equal 1000. Therefore, timer runs from zero to 1000. Gives 0.1Hz resolution.

    // Solving for prescaler gives 240.

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

    TIM_TimeBaseStructInit( &TIM_TimeBaseInitStruct );

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV4;

    TIM_TimeBaseInitStruct.TIM_Period = 1000;

    TIM_TimeBaseInitStruct.TIM_Prescaler = 240;

    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStruct );

 

    TIM_OCInitTypeDef TIM_OCInitStruct;

    TIM_OCStructInit( &TIM_OCInitStruct );

    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;

    // Initial duty cycle equals 0%. Value can range from zero to 1000.

    TIM_OCInitStruct.TIM_Pulse = 0;

    TIM_OC3Init( TIM3, &TIM_OCInitStruct );

    TIM_Cmd( TIM3, ENABLE );

Also, below is a useful macro that sets the PWM duty cycle once the output is running.

// Set duty cycle when using TIM3 as a PWM output.

&sharpdefine SetTIM3Duty( val )    TIM3->CCR3 = val

It's neat to see the blue LED ramping and fading smoothly.

#stm32 #pwm #pwm #discovery #stm32f100rb #output
49 REPLIES 49
Posted on February 14, 2011 at 19:03

FYI, These are zero based

    TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1;  // 0 .. 999

    TIM_TimeBaseInitStruct.TIM_Prescaler = 240 - 1;  // divide by 240

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
John F.
Senior
Posted on February 17, 2011 at 16:38

... and, if you are interested, that should have been ''poring'' ... unless you were using a jug.

kenn
Associate II
Posted on March 17, 2011 at 12:41

Nice code. In addition to Clive's correction, I would suggest updating it with

GPIO_StructInit(&GPIO_InitStructure); // Reset init structure

as this can catch beginners who have already defined and partially filled GPIO_InitStructure elsewhere can get caught up on this.

abelievegu
Associate
Posted on March 18, 2011 at 02:27

I'm so thankful that someone posted a PWM signal example because I was having trouble figuring out how to do it. I really would like to use this code to drive some stepper motors. To test it, I tried just copying and pasting the code to my main function. However, when building the compiler said that GPIO_InitStructure was undeclared. What am I missing?

Posted on March 18, 2011 at 02:48

What am I missing?

  GPIO_InitTypeDef GPIO_InitStructure;

Note also that the FW library comes with some examples, and both IAR and Keil have more extensive examples from the earlier 2.0 library which are also quiet instructive.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 18, 2011 at 02:58

This should be a fairly complete version, integrating all the additional suggestions. I think I've previously posted some other TIM3 and TIM4 examples, but this forum is so busted and external Google search might be more effective. Thanks to JimK for posting his version.

#include ''stm32F10x.h''

#include ''STM32vldiscovery.h''

int main(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

  TIM_OCInitTypeDef TIM_OCInitStruct;

    RCC_APB2PeriphClockCmd( 

            RCC_APB2Periph_GPIOC |

            RCC_APB2Periph_AFIO, ENABLE );

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );

    // Set the Vector Table base address at 0x08000000.

    NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );

    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );

    // Configure HCLK clock as SysTick clock source.

    SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );

    GPIO_StructInit(&GPIO_InitStructure); // Reset init structure

    // Setup Blue LED on STM32-Discovery Board to use PWM.

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            // Alt Function - Push Pull

    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_PinRemapConfig( GPIO_FullRemap_TIM3, ENABLE );        // Map TIM3_CH3 to GPIOC.Pin8

    // Let PWM frequency equal 100Hz.

    // Let period equal 1000. Therefore, timer runs from zero to 1000. Gives 0.1Hz resolution.

    // Solving for prescaler gives 240.

    TIM_TimeBaseStructInit( &TIM_TimeBaseInitStruct );

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV4;

    TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1;   // 0..999

    TIM_TimeBaseInitStruct.TIM_Prescaler = 240 - 1; // Div 240

    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStruct );

    TIM_OCStructInit( &TIM_OCInitStruct );

    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;

    // Initial duty cycle equals 0%. Value can range from zero to 1000.

    TIM_OCInitStruct.TIM_Pulse = 0; // 0 .. 1000 (0=Always Off, 1000=Always On)

    TIM_OC3Init( TIM3, &TIM_OCInitStruct );

    TIM_Cmd( TIM3, ENABLE );

  while(1); // Do not exit

  return(0); // System will implode

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
harshana_n
Associate II
Posted on April 11, 2011 at 12:22

Hello,

I have copied your code below and try to run it but i don't seem to get the blue led running :(

I cleared out all the coding generated by true studio but still i get the same result.. when i copy and run your code below i can see the registers changing but it doesn't seem to work the blue LED some help please

''#include ''stm32F10x.h''

#include ''STM32vldiscovery.h''

int main(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

  TIM_OCInitTypeDef TIM_OCInitStruct;

    RCC_APB2PeriphClockCmd(

            RCC_APB2Periph_GPIOC |

            RCC_APB2Periph_AFIO, ENABLE );

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );

    // Set the Vector Table base address at 0x08000000.

    NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );

    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );

    // Configure HCLK clock as SysTick clock source.

    SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );

    GPIO_StructInit(&GPIO_InitStructure); // Reset init structure

    // Setup Blue LED on STM32-Discovery Board to use PWM.

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            // Alt Function - Push Pull

    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_PinRemapConfig( GPIO_FullRemap_TIM3, ENABLE );        // Map TIM3_CH3 to GPIOC.Pin8

    // Let PWM frequency equal 100Hz.

    // Let period equal 1000. Therefore, timer runs from zero to 1000. Gives 0.1Hz resolution.

    // Solving for prescaler gives 240.

    TIM_TimeBaseStructInit( &TIM_TimeBaseInitStruct );

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV4;

    TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1;   // 0..999

    TIM_TimeBaseInitStruct.TIM_Prescaler = 240 - 1; // Div 240

    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStruct );

    TIM_OCStructInit( &TIM_OCInitStruct );

    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;

    // Initial duty cycle equals 0%. Value can range from zero to 1000.

    TIM_OCInitStruct.TIM_Pulse = 0; // 0 .. 1000 (0=Always Off, 1000=Always On)

    TIM_OC3Init( TIM3, &TIM_OCInitStruct );

    TIM_Cmd( TIM3, ENABLE );

  while(1); // Do not exit

  return(0); // System will implode

}

''

Posted on April 11, 2011 at 19:57

Try picking a 50% duty cycle (500), instead of OFF all the time?

// Initial duty cycle equals 0%. Value can range from zero to 1000.

    TIM_OCInitStruct.TIM_Pulse = 0; // 0 .. 1000 (0=Always Off, 1000=Always On)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hellosujit
Associate
Posted on April 20, 2011 at 22:51

Hi Clive,

We are new to STM32F103ZE i think its similar to STM32VL.. i copy paste the code and change the LED port but it is not working. Is there other way to use timer of our board. We cannot make our any timer program running in this board. If you have any program related to our board which use timer please post it here..

Looking forward for your mail.

Thanks,

Sujit