cancel
Showing results for 
Search instead for 
Did you mean: 

Can't produce 20 ms PWM for servo

nyanlynnhtet07
Associate
Posted on October 25, 2016 at 15:54

Hi. I am quite new to STM32. 

I would like to produce 20ms square PWM with adjustable duty cycle for controlling 2 servo position. 

MCU = stm32f103ret6  Using GNU ARM toolchain on Eclipse cdt. 

Use Timer5 Ch1,2 (PA0, PA1 for servo signal). 

Here is the code I write so far. 

// For GPIO Initialization

void GPIO_Init_Mode_50MHz(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIOMode_TypeDef mode) {

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin;

GPIO_InitStructure.GPIO_Mode = mode;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOx, &GPIO_InitStructure);

}

void InitTimer5_servoPWM(bool bCH1, bool bCH2){

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_OCInitTypeDef  TIM_OCInitStructure;ss

/* TIM5 clock enable */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

     /* Time base configuration */

    TIM_TimeBaseStructure.TIM_Prescaler = 63;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_Period = 20000; // period in usec

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

    /* Output Compare Active Mode configuration: Channel1 */

    TIM_OCStructInit(&TIM_OCInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

//Timer5_CH1(PA0) Timer5_CH2(PA1)

    if (bCH1) {

    GPIO_Init_Mode_50MHz(GPIOA, GPIO_Pin_0, GPIO_Mode_AF_PP);

    /* Output Compare Timing Mode configuration: Channel1 */

    TIM_OC1Init(TIM5, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);

    TIM5->CCR1 = 0;

    }

    if (bCH2) {

    GPIO_Init_Mode_50MHz(GPIOA, GPIO_Pin_1, GPIO_Mode_AF_PP);

        /* Output Compare Timing Mode configuration: Channel1 */

    TIM_OC2Init(TIM5, &TIM_OCInitStructure);

    TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable);

    TIM5->CCR2 = 0;

    }

    TIM_ARRPreloadConfig(TIM5, ENABLE);

    // output enable for TIM5 only

    TIM_CtrlPWMOutputs(TIM5, ENABLE);

    TIM_Cmd(TIM5, ENABLE);

 }

 

 // For changing dutycycle

 void SetTimer5PWM(int16_t ch, int16_t pwm) {

switch(ch) {

case 1 : TIM5->CCR1 = pwm; break;

case 2 : TIM5->CCR2 = pwm; break;

}

}

#stm32f103-pwm #stm32f103-pwm #!adxl345
8 REPLIES 8
Posted on October 25, 2016 at 16:27

Timer runs? (verify e.g. looking at TIM_CNT in debugger)

JW

Posted on October 25, 2016 at 16:30

If you are not getting 20ms period what are you getting? What aspect of this is ''not working'' ?

I'd recommend not using the 50MHz slew-rate setting on a signal below 1MHz

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michaelc.barton9
Associate II
Posted on October 25, 2016 at 16:48

you'll need these lines where you're configuring the GPIO:

GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_??);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_??);

I'm not sure exactly which GPIO_AF_* number you'll need to use as the help docs are a little obtuse for the STM32F1* series :(

Posted on October 25, 2016 at 16:55

The F1 series doesn't support GPIO_PinAFConfig as the AF options are peripheral rather than pin mapped.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
michaelc.barton9
Associate II
Posted on October 25, 2016 at 17:12

oops - yes, was somehow looking at F0 :(

nyanlynnhtet07
Associate
Posted on October 26, 2016 at 03:36

CNT is 0. It doesn't increase. 

When I check with scope, it shows a funny wave that changes between 40k-250kHz and sometimes 1MHz. 

Is there a need to do something like pin map for Timer5 and PA0, PA1? The address of TIM5 is not available in my GPIO firmware library for mapping. 

Posted on October 26, 2016 at 09:20

Then you need to enable it by setting CEN bit in TIMx_CR1. I don't use any of the ''libraries'' but there must be a function or macro for this, refer to your ''library'''s manual.

JW

Posted on October 26, 2016 at 15:15

The TIM5_CH1/2 are default mappings for PA0/PA1 but there are several other peripherals sharing this, and they might need to be remapped if they conflict.

You'd need to check the data-sheet for the specific F1 part to see which TIMx it supports. Generally if the TIM is not present all TIMx->registers will be zero, and the clock enable bit for the APB will be stuck-at-zero.

I've posted numerous servo examples, review older forum posts.

Consider also what else on the board is connected to or using these pins.

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