cancel
Showing results for 
Search instead for 
Did you mean: 

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

ASnow.1
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions
ASnow.1
Associate II

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.

View solution in original post

3 REPLIES 3
ASnow.1
Associate II

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.

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

FBL
ST Employee

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 Accept as Solution on the reply which solved your issue or answered your question.