Skip to main content
james239955_stm1_stmicro_com
Associate II
February 12, 2011
Question

Example: PWM on STM32-Discovery Blue LED

  • February 12, 2011
  • 49 replies
  • 10781 views
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
This topic has been closed for replies.

49 replies

Tesla DeLorean
Guru
February 14, 2011
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 VenmoUp vote any posts that you find helpful, it shows what's working..
John F.
Associate III
February 17, 2011
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
March 17, 2011
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
Visitor II
March 18, 2011
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?

Tesla DeLorean
Guru
March 18, 2011
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 VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
March 18, 2011
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 VenmoUp vote any posts that you find helpful, it shows what's working..
harshana_n
Associate II
April 11, 2011
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

}

''

Tesla DeLorean
Guru
April 11, 2011
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 VenmoUp vote any posts that you find helpful, it shows what's working..
hellosujit
Visitor II
April 20, 2011
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

Tesla DeLorean
Guru
April 23, 2011
Posted on April 23, 2011 at 13:41

Which board? Which pin?

I'm afraid I can't provide any specific help with the information provided.

The example uses a specific timer, and knowledge about which pin(s) that timer is connected to externally. For it to work with different pins/timers, you'd need to review the reference manual to see if the pin you want to use is in fact connected to a timer output channel capable of PWM, and then enable/configure the timer (timebase/channel), gpio, clocks, etc.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..