STM32H7用hal库编程,使用定时器的编码器模式采集光栅尺的信号,一运行程序中断会有异常,没有计数就会进入更新中断

问题遇到的现象和发生背景

STM32H7用hal库编程,使用定时器的编码器模式采集光栅尺的信号,一运行程序中断会有异常,没有计数就会进入更新中断,还会连续进入两次

问题相关代码,请勿粘贴截图

.c文件
#include "bsp_encoder.h"

__IO int16_t Encoder_Overflow_Count = 0;

TIM_HandleTypeDef TIM_EncoderHandle;

static void Encoder_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

ENCODER_TIM_CH1_GPIO_CLK_ENABLE();
ENCODER_TIM_CH2_GPIO_CLK_ENABLE();

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Pull = GPIO_PULLUP;

//GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

GPIO_InitStruct.Pin = ENCODER_TIM_CH1_PIN;

GPIO_InitStruct.Alternate = ENCODER_TIM_CH1_GPIO_AF;

HAL_GPIO_Init(ENCODER_TIM_CH1_GPIO_PORT, &GPIO_InitStruct);

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Pin = ENCODER_TIM_CH2_PIN;

GPIO_InitStruct.Alternate = ENCODER_TIM_CH2_GPIO_AF;

HAL_GPIO_Init(ENCODER_TIM_CH2_GPIO_PORT, &GPIO_InitStruct);
}

static void TIM_Encoder_Init(void)
{
TIM_Encoder_InitTypeDef Encoder_ConfigStructure;

ENCODER_TIM_CLK_ENABLE();

TIM_EncoderHandle.Instance = ENCODER_TIM;
TIM_EncoderHandle.Init.Prescaler = ENCODER_TIM_PRESCALER;
TIM_EncoderHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM_EncoderHandle.Init.Period = ENCODER_TIM_PERIOD;
TIM_EncoderHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TIM_EncoderHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

Encoder_ConfigStructure.EncoderMode = ENCODER_MODE;

Encoder_ConfigStructure.IC1Polarity = ENCODER_IC1_POLARITY;
Encoder_ConfigStructure.IC1Selection = TIM_ICSELECTION_DIRECTTI;
Encoder_ConfigStructure.IC1Prescaler = TIM_ICPSC_DIV1;
Encoder_ConfigStructure.IC1Filter = 0;

Encoder_ConfigStructure.IC2Polarity = ENCODER_IC2_POLARITY;
Encoder_ConfigStructure.IC2Selection = TIM_ICSELECTION_DIRECTTI;
Encoder_ConfigStructure.IC2Prescaler = TIM_ICPSC_DIV1;
Encoder_ConfigStructure.IC2Filter = 0;

HAL_TIM_Encoder_Init(&TIM_EncoderHandle, &Encoder_ConfigStructure);

__HAL_TIM_SET_COUNTER(&TIM_EncoderHandle, 0);

__HAL_TIM_CLEAR_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);

__HAL_TIM_ENABLE_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);

__HAL_TIM_URS_ENABLE(&TIM_EncoderHandle);

HAL_NVIC_SetPriority(ENCODER_TIM_IRQn, 5, 1);

HAL_NVIC_EnableIRQ(ENCODER_TIM_IRQn);

HAL_TIM_Encoder_Start(&TIM_EncoderHandle, TIM_CHANNEL_ALL);

}

void Encoder_Init(void)
{
Encoder_GPIO_Init();
TIM_Encoder_Init();
}

void TIM4_IRQHandler(void)
{
if(__HAL_TIM_IS_TIM_COUNTING_DOWN(&TIM_EncoderHandle))

    Encoder_Overflow_Count-=1;
  else

    Encoder_Overflow_Count+=1;
  __HAL_TIM_CLEAR_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);

}

#ifndef __BSP_ENCOEDER_H
#define __BSP_ENCOEDER_H

#include "stm32h7xx.h"

#define ENCODER_TIM TIM4
#define ENCODER_TIM_CLK_ENABLE() __HAL_RCC_TIM4_CLK_ENABLE()

#define ENCODER_TIM_PERIOD 65535

#define ENCODER_TIM_PRESCALER 0

#define ENCODER_TIM_IRQn TIM4_IRQn
#define ENCODER_TIM_IRQHandler TIM4_IRQHandler

#define ENCODER_TIM_CH1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define ENCODER_TIM_CH1_GPIO_PORT GPIOD
#define ENCODER_TIM_CH1_PIN GPIO_PIN_12
#define ENCODER_TIM_CH1_GPIO_AF GPIO_AF2_TIM4

#define ENCODER_TIM_CH2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define ENCODER_TIM_CH2_GPIO_PORT GPIOD
#define ENCODER_TIM_CH2_PIN GPIO_PIN_13
#define ENCODER_TIM_CH2_GPIO_AF GPIO_AF2_TIM4

#define ENCODER_MODE TIM_ENCODERMODE_TI12

#define ENCODER_IC1_POLARITY TIM_ICPOLARITY_FALLING
#define ENCODER_IC2_POLARITY TIM_ICPOLARITY_RISING

#define ENCODER_RESOLUTION 5000

#if ((ENCODER_MODE == TIM_ENCODERMODE_TI1) || (ENCODER_MODE == TIM_ENCODERMODE_TI2))
#define ENCODER_TOTAL_RESOLUTION (ENCODER_RESOLUTION * 2)
#else
#define ENCODER_TOTAL_RESOLUTION (ENCODER_RESOLUTION * 4)
#endif

extern __IO int16_t Encoder_Overflow_Count;
extern TIM_HandleTypeDef TIM_EncoderHandle;

void Encoder_Init(void);

#endif __BSP_ENCODER_H

运行结果及报错内容

调试的时候将断点放在中断void TIM4_IRQHandler(void)函数内部会直接进入,但是定时器的CNT没有变化,没有计数,一步一步调试会不断进入中断,Encoder_Overflow_Count有变化,去掉断点后,Encoder_Overflow_Count变化一会后就停止了

我的解答思路和尝试过的方法

中断函数改成了现在的,以前是在HAL_TIM_PeriodElapsedCallback(),内部写的,一样的现象。
改过IO的初始化和编码器模式的初始化,不知道是不是初始化的问题,目前没能解决。

我想要达到的结果

怎么能计数到一定值才进入更新中断呢,不想一开始不断进入中断。

报的错内容是什么啊

编译后没有报错,程序一启动就会不断进入编码器模式相应的定时器的更新中断,然后里边的程序就会运行,记录溢出次数的变量就会变化,导致在中断服务函数里什么都干不了