2011-02-12 12:39 PM
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 #output2011-04-23 04:41 AM
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.2011-12-23 03:50 AM
Just replace
while(1);
with
int i;
int n = 1;
int brightness = 0; while(1){ // Do not exit if (brightness >= 1000) n = -1; // if brightness maximum change direction if (brightness <= 0) n = 1; // if brightness minimum change direction
brightness += n; // increment or decrement brightness refer by direction
TIM3->CCR3 = brightness; // set brightness
for(i=0;i<0x400;i++); // delay
}; JimK, thank you very much. This is the first thing that I wanted to do after simple led blinking. It's neat to see the blue LED ramping and fading smoothly.
Playing with stm32vldiscovery for second evening. Now it is time to understand the right way to add PWM to second LED.
2011-12-29 07:06 AM
And that's what i wanted to ask - why is pin 8 automatically remapped to channel 3? Can i remap it to some other channel and how? And btw how to connect both leds on stm32-discovery to pwm?
2011-12-29 07:26 AM
And that's what i wanted to ask - why is pin 8 automatically remapped to channel 3?
The default pin mapping, and remapped options, are clearly defined in the Data Sheet. The timer, channel, and remapping were chosen explicitly because they got the job done, and not picked randomly. See pg 27 http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD002517pdf http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00246pdf2012-01-09 08:15 AM
and congratulations
for the excellent job
on the forum
2012-01-09 10:07 AM
#include ''stm32F10x.h''
#include ''STM32vldiscovery.h''
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
volatile int i;
int n = 1;
int brightness = 0;
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOC |
RCC_APB2Periph_AFIO, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
GPIO_StructInit(&GPIO_InitStructure); // Reset init structure
// Setup Blue & Green LED on STM32-Discovery Board to use PWM.
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
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, TIM3_CH4 to GPIOC.Pin9
// Let PWM frequency equal 100Hz.
// Let period equal 1000. Therefore, timer runs from zero to 1000. Gives 0.1Hz resolution.
// Solving for prescaler gives
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 ); // Channel 3 Blue LED
TIM_OC4Init( TIM3, &TIM_OCInitStruct ); // Channel 4 Green LED
TIM_Cmd( TIM3, ENABLE );
while(1) // Do not exit
{
if (((brightness + n) >= 1000) || ((brightness + n) <= 0))
n = -n; // if brightness maximum/maximum change direction
brightness += n;
TIM3->CCR3 = brightness; // set brightness
TIM3->CCR4 = 1000 - brightness; // set brightness
for(i=0;i<10000;i++); // delay
}
return(0); // System will implode
}
2012-01-09 01:47 PM
I studied the code and data sheet, but i had not looked at the
TIM_OC3Init function. Now everything is clear! Thanks!!
2012-03-23 08:45 AM
I've the same problem, even if I use the complete code of Clive1.
I 've some others errors....I list them: ..\src\main.c(28): error: #20: identifier ''TIM_TimeBaseInitTypeDef'' is undefined ..\src\main.c(29): error: #20: identifier ''TIM_OCInitTypeDef'' is undefined ..\src\main.c(53): warning: #223-D: function ''TIM_TimeBaseStructInit'' declared implicitly ..\src\main.c(54): error: #20: identifier ''TIM_CKD_DIV4'' is undefined ..\src\main.c(57): warning: #223-D: function ''TIM_TimeBaseInit'' declared implicitly ..\src\main.c(59): warning: #223-D: function ''TIM_OCStructInit'' declared implicitly ..\src\main.c(60): error: #20: identifier ''TIM_OutputState_Enable'' is undefined ..\src\main.c(61): error: #20: identifier ''TIM_OCMode_PWM1'' is undefined ..\src\main.c(65): warning: #223-D: function ''TIM_OC3Init'' declared implicitly ..\src\main.c(66): warning: #223-D: function ''TIM_OC4Init'' declared implicitly ..\src\main.c(68): warning: #223-D: function ''TIM_Cmd'' declared implicitly ..\src\main.c(83): warning: #111-D: statement is unreachable a lot of problems are just warning. The software I'm using is the Keil one. I'm new with the programming with this micro (and micro in general), so forgive me if it is a stupid question ;)2012-03-23 12:42 PM
This would seem to be a basic problem with pulling in the appropriate include files.
Try looking at stm32f10x_conf.h, and make sure it's pulling in stm32f10x_tim.h, etc.2012-04-02 04:06 AM
Thanks for the reply.
I try to check the stm32f10_conf.h file and the file stm32f10x_tim.h is commented. In the stm32f10x_tim.h file the only included file is stm32f10x.h I try to remove the comment on stm32f10_conf.h but I have new errors: Following the errors. ..\src\main.c(83): warning: #111-D: statement is unreachable linking... .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TimingDelay_Decrement (referred from stm32f10x_it.o). .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TIM_Cmd (referred from main.o). .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TIM_OC3Init (referred from main.o). .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TIM_OC4Init (referred from main.o). .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TIM_OCStructInit (referred from main.o). .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TIM_TimeBaseInit (referred from main.o). .\Debug\DISCOVER.axf: Error: L6218E: Undefined symbol TIM_TimeBaseStructInit (referred from main.o).