2023-02-27 04:48 PM
Problem
I'm having an issue where, after configuring timer 4 in encoder mode using the HAL, the CNT register is not updating while the encoder is turned. Messed around with it for some days but still can't get it to work.
Hardware
Optical encoder - NPN open-collector pulse lines. Powered by 5v. Using 1k pull-ups to 3.3v.
Connections
PD12 and PD13 as TI1 and TI2
Timer & GPIO Configuration
void MX_TIM4_Init(void)
{
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 65535;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0xF;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0xF;
if (HAL_TIM_Encoder_Init(&htim4, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(tim_encoderHandle->Instance==TIM4)
{
__HAL_RCC_TIM4_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**TIM4 GPIO Configuration
PD12 ------> TIM4_CH1
PD13 ------> TIM4_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
}
Clock Configuration
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3|RCC_PERIPHCLK_USB|RCC_PERIPHCLK_ADC12
|RCC_PERIPHCLK_TIM34;
PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_HSI;
PeriphClkInit.Adc12ClockSelection = RCC_ADC12PLLCLK_DIV1;
PeriphClkInit.USBClockSelection = RCC_USBCLKSOURCE_PLL;
PeriphClkInit.Tim34ClockSelection = RCC_TIM34CLK_PLLCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
Timer start
HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
Notes
I'm running timer 4 off of the PLL*2 output. I can verify that the PLL clock is working as its powering my USB functionality. The timer 4 clock is therefore running at 96MHz. Possibly too fast, but that is about the only thing I can imagine is going wrong. I've changed plenty of things about the configuration, such as input filtering, polarity, GPIO speed, all just to see if I can get it to actually work. No changes to CNT, verified through live expression debugging and UART printing the value. The square waves from the rotary encoder don't have any bounce (as expected from an optical encoder) but have a rise time of about 312ns. Any help will be appreciated
Solved! Go to Solution.
2023-02-27 08:33 PM
Timer 4 didn't work in encoder mode. It works now using Timer 3. I don't know why, but that's the change I had to make.
2023-02-27 08:33 PM
Timer 4 didn't work in encoder mode. It works now using Timer 3. I don't know why, but that's the change I had to make.
2023-02-28 12:12 AM
I don't see any fundamental reason why wouldn't TIM4 run from
The debugging steps might've been:
JW
2023-03-03 07:53 AM
Hello @ASnow.1 ,
It should work for TIM4 in polling and interrupt mode as well. Attached an example TIM4 in encoder mode.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.