Skip to main content
ASnow.1
Associate II
February 28, 2023
Solved

STM32F303ZE (NUCLEO-F303ZE) -- Timer in encoder mode -- CNT register is not incrementing/decrementing.

  • February 28, 2023
  • 3 replies
  • 1340 views

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

This topic has been closed for replies.
Best answer by ASnow.1

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.

3 replies

ASnow.1
ASnow.1AuthorBest answer
Associate II
February 28, 2023

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.

waclawek.jan
Super User
February 28, 2023

I don't see any fundamental reason why wouldn't TIM4 run from

The debugging steps might've been:

  • verifying connectinon to pins by observing bits 12 and 13 in GPIO_IDR while slowly moving the encoder
  • checking all related jumpers/solder bridges on the board
  • reading out and checking/posting content of TIM and related GPIO pins' content
  • trying to avoid clocking of TIM4 from PLL, if it sounds to be a concern

JW

Technical Moderator
March 3, 2023

Hello @ASnow.1​ ,

It should work for TIM4 in polling and interrupt mode as well. Attached an example TIM4 in encoder mode.

0693W00000aI9ZtQAK.png

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL