cancel
Showing results for 
Search instead for 
Did you mean: 

[SOLVED] STM32F103 Generating PWM with TIM4

cyril2
Associate
Posted on June 08, 2016 at 20:10

Hello everyone,

I started with STM32F103 two days ago and I need to generate a PWM on GPIOB pin6 using TIM4. I need a PWM of period 20ms with a 1us precision (System Clock is set to 72 MHz) I have read several tutorial and examples, but I still cannot make it work (no signal, no PWM, nothing) Could anyone check what's wrong with my code ?

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//! Includes
////////////////////////////////////////////////////////////////////////////////
#include ''HIL_CLUTCH.h''
#include ''stm32f10x.h''
#include ''stm32f10x_spi.h''
#include ''stm32f10x_tim.h''
#include ''delay.h''
////////////////////////////////////////////////////////////////////////////////
//! Defines
////////////////////////////////////////////////////////////////////////////////
//typedef enum{eFullOnMode,eCruiseOnMode,eFullOffMode,eCuiseOffMode,eCustomMode} eClutchMode;
#define PORT_CLUTCH GPIOB //PB.6
#define PIN_CLUTCH GPIO_Pin_6
////////////////////////////////////////////////////////////////////////////////
//! Private prototypes
////////////////////////////////////////////////////////////////////////////////
void vHIL_CLUTCH_Init(void) ;
void ClutchTimerInit(uint16_t period) ;
void ClutchPWMInit(void) ;
void ClutchGPIOInit(void) ;
void RCC_Init() ;
////////////////////////////////////////////////////////////////////////////////
//! Private variables
////////////////////////////////////////////////////////////////////////////////
int UptimeMicroSec ; 
////////////////////////////////////////////////////////////////////////////////
//! Private functions
////////////////////////////////////////////////////////////////////////////////
//Calls every function below
void vHIL_CLUTCH_Init(void)
{
RCC_Init() ;
ClutchGPIOInit() ;
ClutchTimerInit(999) ;
ClutchPWMInit() ; 
}
void RCC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
} 
void ClutchTimerInit(uint16_t period) 
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 72 ;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = period;
timerInitStructure.TIM_ClockDivision = 0;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &timerInitStructure);
TIM_Cmd(TIM4, ENABLE); 
}
void ClutchGPIOInit(void)
{
GPIO_InitTypeDef gpioStructure; 
gpioStructure.GPIO_Pin = PIN_CLUTCH;
gpioStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
gpioStructure.GPIO_Speed = GPIO_Speed_50MHz ; 
GPIO_Init(PORT_CLUTCH, &gpioStructure); 
}
void ClutchPWMInit(void)
{ 
TIM_OCInitTypeDef outputChannelInit;
outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
outputChannelInit.TIM_Pulse = 500;
outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &outputChannelInit);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);
}

#tim4 #pwm #stm32f103
3 REPLIES 3
Posted on June 08, 2016 at 21:43

Which STM32F103xx part specifically? Give me a fully qualified part#, not all support TIM4. Available on Medium and High density versions.

PB6 is the Default output for TIM4_CH1, not the Remapped one, so don't remap the pin/peripheral 1MHz from 72 MHz needs Prescaler = 72 - 1; // N steps, 0 .. N-1

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//! Includes
////////////////////////////////////////////////////////////////////////////////
#include ''HIL_CLUTCH.h''
#include ''stm32f10x.h''
#include ''stm32f10x_spi.h''
#include ''stm32f10x_tim.h''
#include ''delay.h''
////////////////////////////////////////////////////////////////////////////////
//! Defines
////////////////////////////////////////////////////////////////////////////////
//typedef enum{eFullOnMode,eCruiseOnMode,eFullOffMode,eCuiseOffMode,eCustomMode} eClutchMode;
#define PORT_CLUTCH GPIOB //PB.6
#define PIN_CLUTCH GPIO_Pin_6
////////////////////////////////////////////////////////////////////////////////
//! Private prototypes
////////////////////////////////////////////////////////////////////////////////
void vHIL_CLUTCH_Init(void) ;
void ClutchTimerInit(uint16_t period) ;
void ClutchPWMInit(void) ;
void ClutchGPIOInit(void) ;
void RCC_Init() ;
////////////////////////////////////////////////////////////////////////////////
//! Private variables
////////////////////////////////////////////////////////////////////////////////
int UptimeMicroSec ; 
////////////////////////////////////////////////////////////////////////////////
//! Private functions
////////////////////////////////////////////////////////////////////////////////
//Calls every function below
void vHIL_CLUTCH_Init(void)
{
RCC_Init() ;
ClutchGPIOInit() ;
ClutchTimerInit(20000) ; // 20ms 20000us
ClutchPWMInit() ;
}
void RCC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
} 
void ClutchTimerInit(uint16_t period) 
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 72 - 1;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = period - 1;
timerInitStructure.TIM_ClockDivision = 0;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &timerInitStructure);
TIM_Cmd(TIM4, ENABLE);
}
void ClutchGPIOInit(void)
{
GPIO_InitTypeDef gpioStructure; 
gpioStructure.GPIO_Pin = PIN_CLUTCH;
gpioStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
gpioStructure.GPIO_Speed = GPIO_Speed_50MHz ; 
GPIO_Init(PORT_CLUTCH, &gpioStructure);
}
void ClutchPWMInit(void)
{ 
TIM_OCInitTypeDef outputChannelInit;
outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
outputChannelInit.TIM_Pulse = 1500; // 1500us
outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &outputChannelInit);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
cyril2
Associate
Posted on June 10, 2016 at 16:45

Thanks for your reply ! The MCU I'm using is STM32F103RB, which is medium density, I think.

Anyway, I tried your code and it works perfectly. Thank you very much !

For the story, I needed a PWM to control a servomotor for a dog clutch in the fuel-efficient vehicle TIM07. With your code, I can initialize the PWM. Then, I just change the duty cycle using TIM4->CCR1 = xxxx.
Posted on June 10, 2016 at 17:33

The 20ms gives it away as a servo application, hence the choice of a value between 1 and 2ms for the pulse width, and using values that meet the requirement specified in the question.

I've covered servos here many times, you can control 4 independently from a single STM32 timer.

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