title: STM32 HAL Nucleo F446RE Quadrature Encoder
body: <p>I have a problem with the quadrature encoder mode on timer TIM3 of my
  <a href="https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f446/stm32f446re.html" rel="nofollow noreferrer">STM32F446RE</a> /
  <a href="https://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/mcu-mpu-eval-tools/stm32-mcu-mpu-eval-tools/stm32-nucleo-boards/nucleo-f446re.html" rel="nofollow noreferrer">NUCLEO-F446RE</a>:</p>
  
  <ol>
  <li><p>TIM3 counts on every rising edge on the first signal.
  The <code>CNT</code> register counts up and I read the value with 1 Hz and then 
  I set the register to 0.</p>
  
  <p>When I look on the
  <a href="https://i.stack.imgur.com/JbM8M.jpg" rel="nofollow noreferrer">oscilloscope</a>
  the frequency is half as high as the value from the
  <a href="https://i.stack.imgur.com/Z0ftD.png" rel="nofollow noreferrer">CNT register output (1hz)</a>.</p>
  
  <p>Why?</p></li>
  <li><p>TIM3 counts on both edges on the first signal.
  The
  <a href="https://i.stack.imgur.com/LEpeC.png" rel="nofollow noreferrer">CNT register output (1 Hz)</a>
  is completely wrong.</p></li>
  </ol>
  
  <p>My configuration is:</p>
  
  <pre><code>GPIO_InitTypeDef sInitEncoderPin1;
  sInitEncoderPin1.Pin                    = pin1Encoder.pin;  // A GPIO_PIN_6
  sInitEncoderPin1.Mode                   = GPIO_MODE_AF_PP;
  sInitEncoderPin1.Pull                   = GPIO_PULLUP;
  sInitEncoderPin1.Speed                  = GPIO_SPEED_HIGH;
  sInitEncoderPin1.Alternate              = altFunctionEncoder; // GPIO_AF2_TIM3
  
  GPIO_InitTypeDef sInitEncoderPin2;
  sInitEncoderPin2.Pin                    = pin2Encoder.pin; // A GPIO_PIN_7
  sInitEncoderPin2.Mode                   = GPIO_MODE_AF_PP;
  sInitEncoderPin2.Pull                   = GPIO_PULLUP;
  sInitEncoderPin2.Speed                  = GPIO_SPEED_HIGH;
  sInitEncoderPin2.Alternate              = altFunctionEncoder; // GPIO_AF2_TIM3
  
  HAL_GPIO_Init(GPIOA, &amp;sInitEncoderPin1);
  HAL_GPIO_Init(GPIOA, &amp;sInitEncoderPin2);
  
  encoderTimer.Init.Period                        = 0xffff;
  encoderTimer.Init.Prescaler                     = 0;
  encoderTimer.Init.CounterMode                   = TIM_COUNTERMODE_UP;
  encoderTimer.Init.ClockDivision                 = TIM_CLOCKDIVISION_DIV1;
  encoderTimer.Init.RepetitionCounter             = 0;
  
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 1);
  
  encoder.EncoderMode                             = TIM_ENCODERMODE_TI1;
  encoder.IC1Filter                               = 0x0f;
  encoder.IC1Polarity                             = TIM_INPUTCHANNELPOLARITY_RISING; // TIM_INPUTCHANNELPOLARITY_BOTHEDGE
  encoder.IC1Prescaler                            = TIM_ICPSC_DIV1;
  encoder.IC1Selection                            = TIM_ICSELECTION_DIRECTTI;
  
  encoder.IC2Filter                               = 0x0f;
  encoder.IC2Polarity                             = TIM_INPUTCHANNELPOLARITY_RISING;
  encoder.IC2Prescaler                            = TIM_ICPSC_DIV1;
  encoder.IC2Selection                            = TIM_ICSELECTION_DIRECTTI;
  
  HAL_TIM_Encoder_Init(&amp;encoderTimer, &amp;encoder);
  HAL_TIM_Encoder_Start_IT(&amp;encoderTimer, TIM_CHANNEL_ALL);
  </code></pre>