2017-03-13 10:05 AM
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!2017-03-14 05:21 AM
>>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.
2017-03-15 03:32 PM
Thanks Clive One. Kind of feels like pretty obvious now that you say that. Thanks again!