AnsweredAssumed Answered

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

Question asked by Muron.Aaron on Mar 13, 2017
Latest reply on Mar 15, 2017 by Muron.Aaron

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!

Outcomes