cancel
Showing results for 
Search instead for 
Did you mean: 

PWM

mosine
Associate II
Posted on July 05, 2013 at 12:20

Hi,

I'm very demoralized to study PWM for stm3220G evaluation board. I need a tutorial/example to understand concepts.

For example: why does gpio_moder configure in AF (alternate function)?

I configured GPIOA1   in my sample project, but I don't see anything with my oscilloscope in that pin (CN1  - 36 PA1| MII_RX_CLK| JP6 open). 

Help me!

12 REPLIES 12
Posted on July 05, 2013 at 12:59

> For example: why does gpio_moder configure in AF (alternate function)?

Because AF is the way how to attach pins to the function modules (Timers, USART, I2S, SPI, Ethernet...). Otherwise, it's a plain input or a plain ''hand-manipulated'' output.

Read RM0033, chapter 6.

> I configured GPIOA1   in my sample project

How?

JW

mosine
Associate II
Posted on July 05, 2013 at 16:32

Thanks for reply. My project is: GPIO (A1) set as output with ODR=1 for 20 msec. After 20msec, ODR=0 and PWM starts in the same GPIO (A1). I'm working with STM3220G evaluation board and I want use tasks (RTOS). I need (problem) set timer (i.e. TIM1) for 20 msec with right systick. How can I do?

Posted on July 05, 2013 at 17:30

This all pretty hopeless.

Here's a quick blind implementation doing 50 Hz (20 ms - servo) out of PA.1

// STM32 PWM 50 Hz (20 ms) STM32F2 PA.1 - sourcer32@gmail.com
#include ''stm32f2xx.h''
/**************************************************************************************/
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// Modulate PA.1 width here 
}
}
/**************************************************************************************/
void RCC_Configuration(void)
{
/* --------------------------- System Clocks Configuration -----------------*/
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM1 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*-------------------------- GPIO Configuration ----------------------------*/
/* GPIOD Configuration: Pins 1 in output push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM2 pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2); // PA1 TIM2_CH2
}
/**************************************************************************************/
void TIM2_Configuration(void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration - SystemCoreClock = 120000000 for 120 MHz board */
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1); // Shooting for 1 MHz, (1us)
TIM_TimeBaseStructure.TIM_Period = 20000 - 1; // 1 MHz / 20000 = 50 Hz (20ms)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Enable TIM2 Preload register on ARR */
TIM_ARRPreloadConfig(TIM2, ENABLE);
/* TIM PWM1 Mode configuration: Channel */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1500; // Servo Top-Center
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/* Output Compare PWM1 Mode configuration: Channel2 PA.1 */
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
/* TIM2 Interrupts enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
TIM2_Configuration();
while(1)
{
// Add code to do something here
}
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mosine
Associate II
Posted on July 08, 2013 at 08:32

Hi,

THANKS Clive!!!! I have sample another question: is there a formula to calculate time? I need a formula to understand this:

TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1); // Shooting for 1 MHz, (1us)
TIM_TimeBaseStructure.TIM_Period = 20000 - 1; // 1 MHz / 20000 = 50 Hz (20ms)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;

Thanks. Simone
mosine
Associate II
Posted on July 08, 2013 at 10:59

If I want stop the pwm, can I do? I see an item of forum, and the timer is stopped to stop pwm. Is there an alternative?

THANKS

Posted on July 08, 2013 at 13:15

The computation is one of factors, which are then divided into the TIMCLK. If APB1 is running at DIV4, then TIMCLK2 is at DIV2 (ie 60 MHz in a 120 MHz system). If I divide 60 MHz by 60 I have a 1 MHz time base. The period of each tick is 1000 ns or 1 us, 20000 ticks of that is 20 ms. This thus defines the periodicity of the pulses. The duty is controlled by the CCRx register for the channel.

TIM2->CCR2 = 0 should have the impact of turning off the pulse (ie always low), TIM2->CCR2 = 20000 should have it be on (ie always high). The timer still ticks, the update interrupt keeps firing.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mosine
Associate II
Posted on July 08, 2013 at 15:37

Hi,

thanks clive1 for your reply. I used two counters to control tick in timer interrupt handler. If I want use internal register to compare time, how can I do? 

thanks

Posted on July 08, 2013 at 17:18

I used two counters to control tick in timer interrupt handler. If I want use internal register to compare time, how can I do?

Not sure I understand the question. The counter timebase ticks in TIMx->CNT, values of which can be latched in TIMx->CCRx in certain timer modes.

If you are counting interrupts by incrementing a ticker value, you can compute a simple delta. The STM32 M3/M4 parts also have a 32-bit cycle counter (120 MHz on an F2 running at that rate), which can be used to make fine granularity measurements.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mosine
Associate II
Posted on July 09, 2013 at 10:03

Hi,

thanks clive1. I create my project by your helps, but now I have a problem to synchronize two timers (I think). I see in myoscilloscope that my wave form is not regular, sometimes (random) start of my wave form is moved. This is my code:

#include ''stm32f2xx.h''
#include <RTL.h>
#include ''stm32f2xx_rcc.h''
#include ''stm32f2xx_tim.h''
#include ''stm32f2xx_gpio.h''
int
start = 0;
int
doPwm = 0;
unsigned 
int
counterTimeStart = 0;
unsigned 
int
counterTimePwm = 0;
unsigned 
int
period = 0;
OS_TID t_pwm_start;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
void
RCC_Configuration(
void
)
{
/*TIM3*/
//RCC->APB1ENR |= (1<<1);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/*TIM2*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
}
/**************************************************************************************/
void
GPIO_ConfigurationStart(unsigned 
int
mod)
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIOA->ODR = mod; 
//0x0002;
}
/**************************************************************************************/
void
NVIC_Configuration(
void
)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void
TIM3_Configuration(
void
){
/* Time base configuration - SystemCoreClock = 120000000 for 120 MHz board */
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1); 
// Shooting for 1 MHz, (1us)
TIM_TimeBaseStructure.TIM_Period = 100 - 1; 
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Enable TIM2 Preload register on ARR */
TIM_ARRPreloadConfig(TIM3, ENABLE);
/* TIM3 Interrupts enable */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
//TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
void
TIM2_Configuration(
void
)
{
/* Time base configuration - SystemCoreClock = 120000000 for 120 MHz board */
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (((SystemCoreClock / 1000000) / 2) - 1); 
// Shooting for 1 MHz, (1us)
TIM_TimeBaseStructure.TIM_Period = 1000 - 1; 
// 1 MHz / 20000 = 50 Hz (20ms)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Enable TIM2 Preload register on ARR */
TIM_ARRPreloadConfig(TIM2, ENABLE);
/* TIM PWM1 Mode configuration: Channel */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 300; 
// Servo Top-Center
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
/* Output Compare PWM1 Mode configuration: Channel1 PA.1 */
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
/* TIM2 Interrupts enable */
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, DISABLE);
}
void
GPIO_Configuration(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM2 pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2); 
// PA1 TIM2_CH2
}
void
enableTIM2(
char
com){
if
(com == 1){
TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
else
{
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
TIM_Cmd(TIM2, DISABLE);
}
}
void
TIM3_IRQHandler(
void
)
{ 
if
(TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
//------------------------
// 20 MSEC
//------------------------
if
(start == 0){
if
(counterTimeStart == 199){
counterTimeStart = 0;
start = 1;
}
else
{
counterTimeStart = counterTimeStart + 1;
}
}
//------------------------
// PWM
//------------------------
if
(start == 1){
if
(doPwm == 0){
GPIO_Configuration();
enableTIM2(1);
}
doPwm = 1;
}
//------------------------
// STOP PERIOD
//------------------------
if
(start == 2){
if
(period == 500){
period = 0;
start = 0;
doPwm = 0;
GPIO_ConfigurationStart(0x0002);
}
else
{
period = period + 1;
}
}
}
}
void
TIM2_IRQHandler(
void
)
{
if
(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if
(counterTimePwm == 5){
counterTimePwm = 0;
enableTIM2(0);
GPIO_ConfigurationStart(0x0000);
start = 2;
}
else
{
counterTimePwm = counterTimePwm + 1;
}
}
}
int
main(
void
)
{
RCC_Configuration();
GPIO_ConfigurationStart(0x0002);
NVIC_Configuration();
TIM3_Configuration();
TIM2_Configuration();
while
(1){
} 
}