cancel
Showing results for 
Search instead for 
Did you mean: 

Is it possible to use Encoder and PWM from the same timer?

Aaron M
Associate
Posted on March 13, 2017 at 18:05

Hi all,

I am new to the STM32 and I am struggling with determining whether or not I can get PWM and Encoder input working on the same timer.

I have a Nucleo-F103 board and using CubeMX, I have set up my board to use Timer1 as both an encoder input and PWM output. Encoder inputs are on channel 1 and channel 2 of Timer1, and the PWM output is on Timer3.

I am using the HAL drivers and have generated the initialization code with CubeMX, and I am working in IAR FWIW. I can get PWM out of channel 3 as long as I do not initialize the HAL Encoder driver (HAL_TIM_Encoder_Init()).

Here is my slightly modified Timer 1 initialization code:

/* TIM1 init function */

static void MX_TIM1_Init(void)

{

uwPeriod = (SystemCoreClock / 20000 ) - 1;

uwPulse = (25 * (uwPeriod - 1)) / 100;

TIM_Encoder_InitTypeDef sConfig;

TIM_MasterConfigTypeDef sMasterConfig;

TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

TIM_OC_InitTypeDef sConfigOC;

htim1.Instance = TIM1;

htim1.Init.Prescaler = 0;

htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

htim1.Init.Period = uwPeriod;

htim1.Init.ClockDivision = 0;//TIM_CLOCKDIVISION_DIV1;

htim1.Init.RepetitionCounter = 0;

if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)

{

Error_Handler();

}

sConfig.EncoderMode = TIM_ENCODERMODE_TI1;

sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;

sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;

sConfig.IC1Prescaler = TIM_ICPSC_DIV1;

sConfig.IC1Filter = 0;

sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;

sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;

sConfig.IC2Prescaler = TIM_ICPSC_DIV1;

sConfig.IC2Filter = 0;

//As long as I comment out this Encoder_Init I can get PWM

/* if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)

{

Error_Handler();

}

*/

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)

{

Error_Handler();

}

sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;

sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

sBreakDeadTimeConfig.DeadTime = 1;

sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)

{

Error_Handler();

}

sConfigOC.OCMode = TIM_OCMODE_PWM2;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;

sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;

sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;

sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

sConfigOC.Pulse = uwPulse;

if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)

{

Error_Handler();

}

HAL_TIM_MspPostInit(&htim1);

}

And in my main.c I start the PWM with HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);

This seems to work fine as long as I do not initialize the encoder driver on Timer 1.

So is it possible to use both encoder and pwm on the same timer? If so, what am I doing wrong or can someone point me in the right direction so I can get started on figuring this out? I haven't found anywhere where it is explicitly stated this is not possible so I would think it is but I can't figure it out!

Thanks in advance!
2 REPLIES 2
Posted on March 14, 2017 at 13:21

>>So is it possible to use both encoder and pwm on the same timer?

No, each timer has a single counting element, so it can either up/down count pulses, or define a period. It is not going to free run in encoder mode.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 15, 2017 at 22:32

Thanks Clive One. Kind of feels like pretty obvious now that you say that. Thanks again!