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 June 03, 2014 at 13:12

Any ideas why this is happening?

Yes, randomly declaring variables in the middle of a subroutine is a C++ syntax, for real C the variable definitions need to be made at the opening scope (ie '{') before any code statements.

If your code was in MAIN.CPP your compiler might tolerate it.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chen
Associate II
Posted on June 03, 2014 at 13:49

Hi

'' #268: declaration may not appear after executable statement in block ''

means you cannot declare variables after code, variables must be declared at the start of a function block.

''

//TIM 3 Config 

void Timer_Configuration_Sec(void)

{

GPIO_InitTypeDef  GPIO_InitStructure;

// Setup LED as PWM output

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_PinRemapConfig( GPIO_FullRemap_TIM3, ENABLE ); //LED connected to Pin 6, Port C

 

TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;

  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInitStruct.TIM_Period = Timer_Period_Value;

TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

  //TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;

TIM_TimeBaseInitStruct.TIM_Prescaler = Timer_Prescaler_Value_Sec;

  TIM_TimeBaseInit(Timer_Used_Sec,&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 = SetTIM3Duty(0); 

TIM_OC3Init( TIM3, &TIM_OCInitStruct ); // Initialize Timer Channel 3 setup

TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

// TIM_ClearITPendingBit(Timer_Used_Sec,TIM_IT_Update);

// TIM_ITConfig(Timer_Used_Sec,TIM_IT_Update,ENABLE);

// TIM_Cmd(Timer_Used_Sec,ENABLE);

}''

I have highlighted the offending lines. Strange the compiler picked up on he 2nd instance?!?

ronan2308
Associate II
Posted on March 18, 2015 at 19:27

When i run this code I keep getting errors like these;

linking...

.\ro6.axf: Error: L6218E: Undefined symbol GPIO_Init (referred from main.o).

.\ro6.axf: Error: L6218E: Undefined symbol GPIO_PinAFConfig (referred from main.o).

.\ro6.axf: Error: L6218E: Undefined symbol RCC_AHBPeriphClockCmd (referred from main.o).

.\ro6.axf: Error: L6218E: Undefined symbol RCC_APB1PeriphClockCmd (referred from main.o).

I'm new enough to using the board so could be a small thing. Any ideas what I'm doing wrong?

Posted on March 18, 2015 at 19:46

You'd need to add the stm32xxx_rcc.c and stm32xxx_gpio.c files into your project.

/public/STe2ecommunities/mcu/Lists/STM32Discovery/Attachments/13561/keil_stm32l_proj.jpg

________________

Attachments :

keil_stm32l_proj.jpg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzsG&d=%2Fa%2F0X0000000bSP%2FmFOdz0aHKjmXlFuIbE9eYkjEOVZo7aPVgeUqIZ9l474&asPdf=false
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ronan2308
Associate II
Posted on March 18, 2015 at 19:59

Clive, 

I already have those files in my project folder and have the pathway to the folder containing all the files chosen. 

Posted on March 18, 2015 at 20:13

I already have those files in my project folder and have the pathway to the folder containing all the files chosen. 

 

ZIP/RAR the project tree, I'll rack it up here and see. The error messages suggest it's not pulling that stuff in.

The other meta-data in the project are the preprocessor defines ''USE_STDPERIPH_DRIVER, STM32L1XX_HD, USE_STM32L152D_EVAL''

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ronan2308
Associate II
Posted on March 20, 2015 at 11:23

Thats my project that I have been trying to get working.

________________

Attachments :

ro4.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzzH&d=%2Fa%2F0X0000000bSM%2Fi9yOef9NeC0erU.HOd.o96yCuxyE1Majaa9o7TBjynU&asPdf=false
Posted on March 20, 2015 at 21:31

Ok, that's just the project definition file, not the project. Doesn't look like you have the defines set.

0690X0000060MoFQAU.gif

0690X00000603JZQAY.jpg

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cerny
Associate
Posted on December 13, 2015 at 17:24

Hello,

I tried get PWM output on pin PA After lot of time I still can't do it. Can you help me please? Here is the code: Comented parts works on PC7, so I tried changed values.

//RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE );
//RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE ); 
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
GPIO_StructInit(&GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
//GPIO_Init( GPIOC, &GPIO_InitStructure );
//GPIO_PinRemapConfig( GPIO_FullRemap_TIM3, ENABLE ); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init( GPIOA, &GPIO_InitStructure ); 
TIM_TimeBaseStructInit( &TIM_TimeBaseInitStruct ); 
TIM_TimeBaseInitStruct.TIM_Prescaler = 24-1;
TIM_TimeBaseInitStruct.TIM_Period = 20000 - 1; 
TIM_OCStructInit( &TIM_OCInitStruct );
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
//TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStruct );
//TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
//TIM_OC2Init( TIM3, &TIM_OCInitStruct ); 
//TIM_Cmd( TIM3, ENABLE );
TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStruct );
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OC3Init( TIM1, &TIM_OCInitStruct ); 
TIM_Cmd( TIM1, ENABLE );
//TIM3->CCR2 = 1000;
TIM1->CCR3 = 1000;

Posted on December 13, 2015 at 20:06

    /* Main Output Enable, and Input */

  TIM_CtrlPWMOutputs(TIM1, ENABLE);

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