cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F29 PWM with Timer 2

Daattavya Aggarwal
Associate II
Posted on August 08, 2017 at 19:47

In my code for pwm on timer 2 in stm32F429, I have to use multiple channels (2 at a time). However only my channel 1 pin is giving pwm output. Please advise me what to do

void enable_gpio1()//setting pin 5 of port a for AF1 which corresponds to timer 2.

{

RCC ->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //Enables port A input output pins by setting the corresponding bit in advanced high performance bus 1 register.

GPIOA ->MODER |= GPIO_MODER_MODER5_1; //Configures pin 5 for alternate function mode by setting the corresponding bit in the mode register

GPIOA ->OTYPER &= ~(GPIO_OTYPER_OT_5); //Makes the output type as push-pull by resetting the corresponding bit in output type register.

GPIOA ->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5_1;//Makes the output high speed.

GPIOA ->PUPDR &= ~(GPIO_PUPDR_PUPDR5);//No pull up or pull down.

GPIOA ->AFR[0] = GPIO_AF1_TIM2<<20;//Sets the AF1 bit in the AFRL(AFR[0]) register which links AF1 to pin A5

}

void enable_gpio2()//setting pin 2 of port a for AF1 which corresponds to timer 2.

{

RCC ->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //Enables port A input output pins by setting the corresponding bit in advanced high performance bus 1 register.

GPIOA ->MODER |= GPIO_MODER_MODER2_1; //Configures pin 5 for alternate function mode by setting the corresponding bit in the mode register

GPIOA ->OTYPER &= ~(GPIO_OTYPER_OT_2); //Makes the output type as push-pull by resetting the corresponding bit in output type register.

GPIOA ->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2_1;//Makes the output high speed.

GPIOA ->PUPDR &= ~(GPIO_PUPDR_PUPDR2);//No pull up or pull down.

GPIOA ->AFR[0] = GPIO_AF1_TIM2<<20;//Sets the AF1 bit in the AFRL(AFR[0]) register which links AF1 to pin A5

}

void generate_pwm1(int n)

{

TIM2 ->CCMR1 |= TIM_CCMR1_OC1M_2;

TIM2 ->CCMR1 |= TIM_CCMR1_OC1M_1;

TIM2 ->CCMR1 &= ~(TIM_CCMR1_OC1M_0);//Selects pwm mode 1 by writing 110

TIM2 ->CCMR1 |= TIM_CCMR1_OC1PE;//

TIM2 ->CR1 |= TIM_CR1_ARPE;//Enables preload register

TIM2 ->EGR |= TIM_EGR_UG;//Enables update event whenever cnt equals ccr.

TIM2 ->CCER |= TIM_CCER_CC1P;//Sets the polarity of the pwm

TIM2 ->CCER |= TIM_CCER_CC1E;

TIM2 ->ARR = (int)n*40/250.0;//Sets the value for the auto reload register.

TIM2 ->CCR1 = 1;//Sets the value for the ccr register.

TIM2 ->CR1 |= TIM_CR1_CEN;//Starts the counter for timer 2.

}

void generate_pwm2(int n)

{

TIM2 ->CCMR2 |= TIM_CCMR2_OC3M_2;

TIM2 ->CCMR2 |= TIM_CCMR2_OC3M_1;

TIM2 ->CCMR2 &= ~(TIM_CCMR2_OC3M_0);//Selects pwm mode 1 by writing 110

TIM2 ->CCMR2 |= TIM_CCMR2_OC3PE;//

TIM2 ->CR1 |= TIM_CR1_ARPE;//Enables preload register

TIM2 ->EGR |= TIM_EGR_UG;//Enables update event whenever cnt equals ccr.

TIM2 ->CCER |= TIM_CCER_CC3P;//Sets the polarity of the pwm

TIM2 ->CCER |= TIM_CCER_CC3E;

TIM2 ->ARR = (int)n*40/250.0;//Sets the value for the auto reload register.

TIM2 ->CCR3 = 1;//Sets the value for the ccr register.

TIM2 ->CR1 |= TIM_CR1_CEN;//Starts the counter for timer 2.

My channel 1 pwm is working but channel 3 is not. I have also included the code I have used to enable the gpio pins.

#timer2 #stm32 #pwm
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on August 09, 2017 at 00:02

Hello again Daattavya.

In STM32F429-DISC board PA1 is connected to INT pin of MEMS that by default is keeped low 

You have two choices.  To init L3GD20  and to make INT1 open drain output .. or to use another AF pin for same channel  PB3  Be aware also that PB3 is used as trace data pin . (not con. by default)

View solution in original post

11 REPLIES 11
Posted on August 08, 2017 at 20:03

void enable_gpio2()//setting pin 2 of port a for AF1 which corresponds to timer 2.

...

GPIOA ->AFR[0] = GPIO_AF1_TIM2<<20;//Sets the AF1 bit in the AFRL(AFR[0]) register which links AF1 to pin A5

it overwrites the previous setting of GPIOA->AFR[0]; and it does not set AF for pin 2.

JW

PS. Do you have a debugger? You could make these settings in the debugger, too; and you could also check them back.

Posted on August 08, 2017 at 20:04

Hello, which board are you use?

Posted on August 08, 2017 at 20:05

GPIOA ->AFR[0] = GPIO_AF1_TIM2<<20;//Sets the AF1 bit in the AFRL(AFR[0]) register which links AF1 to pin A5

Don't do blind writes into registers that already have content in them, and make sure if you want to set pin 2 you don't configure pin 5

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Daattavya Aggarwal
Associate II
Posted on August 08, 2017 at 23:33

I made the change regarding the linking of alternate function with the GPIO pins. I am now using channel 1 and channel 2 so I have configured PA5 and PA1 using the following commands:

GPIOA ->AFR[0] = GPIO_AF1_TIM2<<20; // Links pin 5 with AF1

GPIOA ->AFR[0] |= GPIO_AF1_TIM2<<4; // Links pin 1 with AF1

As I have to use multiple pwm channels with the same timer, I have used bitwise or( | ). This should ensure that pin 1 gets linked without affecting pin 5, right? However my code is still not working. Any suggestions?

void enable_gpio1()

{

RCC ->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; 

GPIOA ->MODER |= GPIO_MODER_MODER5_1; 

GPIOA ->OTYPER &= ~(GPIO_OTYPER_OT_5); 

GPIOA ->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5_1;

GPIOA ->PUPDR &= ~(GPIO_PUPDR_PUPDR5);

GPIOA ->AFR[0] = GPIO_AF1_TIM2<<20;

}

void enable_gpio2()

{

RCC ->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; 

GPIOA ->MODER |= GPIO_MODER_MODER1_1; 

GPIOA ->OTYPER &= ~(GPIO_OTYPER_OT_1);

GPIOA ->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR1_1;

GPIOA ->PUPDR &= ~(GPIO_PUPDR_PUPDR1);

GPIOA ->AFR[0] |= GPIO_AF1_TIM2<<4;

}

void generate_pwm1()

{

TIM2 ->CCMR1 |= TIM_CCMR1_OC1M_2;

TIM2 ->CCMR1 |= TIM_CCMR1_OC1M_1;

TIM2 ->CCMR1 &= ~(TIM_CCMR1_OC1M_0);//Selects pwm mode 1 by writing 110

TIM2 ->CCMR1 |= TIM_CCMR1_OC1PE;//

TIM2 ->CR1 |= TIM_CR1_ARPE;//Enables preload register

TIM2 ->EGR |= TIM_EGR_UG;//Enables update event whenever cnt equals ccr.

TIM2 ->CCER &= ~(TIM_CCER_CC1P);//Sets the polarity of the pwm

TIM2 ->CCER |= TIM_CCER_CC1E;

TIM2 ->ARR = 500;//Sets the value for the auto reload register.

TIM2 ->CCR1 = 50;//Sets the value for the ccr register.

TIM2 ->CR1 |= TIM_CR1_CEN;//Starts the counter for timer 2.

}

void generate_pwm2()

{

TIM2 ->CCMR1 |= TIM_CCMR1_OC2M_2;

TIM2 ->CCMR1 |= TIM_CCMR1_OC2M_1;

TIM2 ->CCMR1 &= ~(TIM_CCMR1_OC2M_0);//Selects pwm mode 1 by writing 110

TIM2 ->CCMR1 |= TIM_CCMR1_OC2PE;//

TIM2 ->CR1 |= TIM_CR1_ARPE;//Enables preload register

TIM2 ->EGR |= TIM_EGR_UG;//Enables update event whenever cnt equals ccr.

TIM2 ->CCER |= TIM_CCER_CC2P;//Sets the polarity of the pwm

TIM2 ->CCER |= TIM_CCER_CC2E;

TIM2 ->ARR = 500;//Sets the value for the auto reload register.

TIM2 ->CCR2 = 400;//Sets the value for the ccr register.

TIM2 ->CR1 |= TIM_CR1_CEN;//Starts the counter for timer 2.

}

Again my channel 1 is working, that is, PA5 is giving pwm output however channel 2 is not.

Posted on August 08, 2017 at 23:04

I am using stm32f429 discovery board.

Posted on August 08, 2017 at 23:06

I do have a debugger. I'll try making these settings. Thanks.

Posted on August 09, 2017 at 00:02

Hello again Daattavya.

In STM32F429-DISC board PA1 is connected to INT pin of MEMS that by default is keeped low 

You have two choices.  To init L3GD20  and to make INT1 open drain output .. or to use another AF pin for same channel  PB3  Be aware also that PB3 is used as trace data pin . (not con. by default)

Posted on August 09, 2017 at 16:43

Hello!

@'Could you tell me how to initiate L3GD20? I checked the user manual but couldn't figure it out.'

By writing,

before your initialisation functions and just after HAL_Init()

;  

GYRO_IO_Init();//enable device

uint8_t ctrl3 = 0x10;

GYRO_IO_Write(&ctrl3, L3GD20_CTRL_REG3_ADDR, 1); //open drain

You must allready have include in your main file  #include 'l3gd20.h'

and add in your project the modules stm32f4xx_hal_spi.c,stm32f4xx_hal_i2c.c(tweak also HAL_conf.h) ,stm32f429i_discovery.c, l3gd20.c and include the coresponding header files.

All theese files are inside your STM32Cube_FW_F4_V1.1x.0\ directory.

Posted on August 09, 2017 at 14:55

Could you tell me how to initiate L3GD20? I checked the user manual but couldn't figure it out.