硬汉嵌入式论坛

 找回密码
 立即注册
查看: 690|回复: 9
收起左侧

[技术讨论] STM32 比较输出模式输出可控数量脉冲---中断状态寄存器异常问题

[复制链接]

0

主题

11

回帖

11

积分

新手上路

积分
11
发表于 2022-11-23 11:19:42 | 显示全部楼层 |阅读模式
本帖最后由 历史的天空 于 2022-11-23 11:23 编辑



STM32 定时器(TIM5 普通定时器)比较输出模式输出可控数量脉冲控制步进马达,单路控制没有问题(只使用TIM5->CHN1),但同时使用两路CHN,出现问题,排查问题发现,问题出在当仅触发CHN1的比较输出中断时,进入中断处理函数,4路CHN+UPG状态位 竟然同时置位(看下面截图)。

按照手册的描述,只会有CC1IF 被置位才对。

下面是的初始化函数和触发函数
int focus_motor_timer_init(void)
{
        GPIO_InitTypeDef         GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef        TIM_OCInitStructure;
        NVIC_InitTypeDef         NVIC_InitStructure;
      
        uint16_t timer_period = ((SystemCoreClock / TIM5_PSC) / 600);

        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
        TIM_OCStructInit(&TIM_OCInitStructure);
        //TIM_ICStructInit(&TIM_ICInitStructure);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,  ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  

        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
        TIM_TimeBaseStructure.TIM_Period            = timer_period -1;
        TIM_TimeBaseStructure.TIM_Prescaler         = TIM5_PSC - 1;
        TIM_TimeBaseStructure.TIM_ClockDivision     = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
  
        GPIO_Set(GPIOA, PIN0, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_100M, GPIO_PUPD_PD);
        GPIO_AF_Set(GPIOA, 0, GPIO_AF_TIM5);
      
        TIM_OCStructInit(&TIM_OCInitStructure);
        TIM_OCInitStructure.TIM_OCMode      = TIM_OCMode_Toggle;        //TIM_OCMode_PWM1 也一样的现象
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_OCPolarity  = TIM_OCPolarity_High;
        TIM_OCInitStructure.TIM_Pulse       = (uint32_t)((timer_period / 2) - 1);  //50%占空比
        TIM_OC1Init(TIM5, &TIM_OCInitStructure);           
        TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Disable);
      
        NVIC_InitStructure.NVIC_IRQChannel                   = TIM5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
      
        TIM_ITConfig(TIM5, TIM_IT_CC1, ENABLE);
        TIM_Cmd(TIM5,DISABLE);
}

int motor_trig(bool dir, uint32_t number, uint32_t freq)
{
        TimerPeriod = ((SystemCoreClock / TIM5_PSC) / freq);

        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_TimeBaseStructure.TIM_Period            = (TimerPeriod - 1);     //自动重装载寄存器周期的值,溢出值
        TIM_TimeBaseStructure.TIM_Prescaler         = TIM5_PSC - 1;        //时钟频率预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision     = TIM_CKD_DIV1;        //设置时钟分割:输入捕获模式用来滤波
        TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;                   //设置重复溢出次数,就是多少次溢出后进入中断,一般为0,只有高级定时器才有用
        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);        
      
        TIM_OCInitTypeDef        TIM_OCInitStructure;
        TIM_OCStructInit(&TIM_OCInitStructure);                                   //设置缺省值,这一步最好加上
        TIM_OCInitStructure.TIM_OCMode      = TIM_OCMode_PWM1;                    //翻转模式定时器引脚同时输出pwm 这样就不用翻转任意io了
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;             //比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity  = TIM_OCPolarity_High;                //输出极性:TIM输出比较极性高      
        TIM_OCInitStructure.TIM_Pulse       = (uint32_t)((TimerPeriod / 2) - 1); //设置待装入捕获比较寄存器的脉冲值
        TIM_OC1Init(TIM5, &TIM_OCInitStructure);           
        TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Disable);
   
        TIM_Cmd(TIM5, ENABLE);
}

4路CHN+UPG同时置位

4路CHN+UPG同时置位



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-11-24 01:14:23 | 显示全部楼层
怎么个用法,CH1,CH2这种通道方式吗,还是互补输出模式。

另外你使用不同的CC中断的话,你要单独开中断的,CC1,CC2,CC3,CC4
回复

使用道具 举报

0

主题

11

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2022-11-29 16:00:44 | 显示全部楼层
eric2013 发表于 2022-11-24 01:14
怎么个用法,CH1,CH2这种通道方式吗,还是互补输出模式。

另外你使用不同的CC中断的话,你要单独开中断 ...

不是互补通道,逻辑上是两个独立的CHN。我确实是单独开的中断,麻烦帮忙看看两个通道的初始化是否有问题?

int dual_chn_motor_timer_init(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
       
        TIM5->CR1 &= ~TIM_CR1_CEN;
       
        uint16_t timer_period = ((SystemCoreClock / TIM5_PSC) / 1500);
       
        RCC->APB1ENR |= RCC_APB1Periph_TIM5;
       
        RCC->AHB1ENR |= RCC_AHB1Periph_GPIOA;
       
        GPIO_Set(GPIOA, PIN0, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_100M, GPIO_PUPD_PD);
        GPIO_Set(GPIOA, PIN1, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_100M, GPIO_PUPD_PD);
        GPIO_AF_Set(GPIOA, 0, GPIO_AF_TIM5);
        GPIO_AF_Set(GPIOA, 1, GPIO_AF_TIM5);

    TIM5->PSC   = TIM5_PSC - 1;
    TIM5->ARR   = timer_period - 1;
    TIM5->CCR1  = (uint32_t)((timer_period / 2) - 1);
        TIM5->CCR2  = (uint32_t)((timer_period / 2) - 1);
    TIM5->CCMR1 = (uint16_t)((TIM_OCMode_PWM1 << 0) | (TIM_OCPreload_Enable << 0) | (TIM_OCMode_PWM1 << 8) | (TIM_OCPreload_Enable << 8));
    TIM5->SR    = 0;

        TIM_ITConfig(TIM5, TIM_IT_CC1, ENABLE);
        NVIC_InitStructure.NVIC_IRQChannel                   = TIM5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
        TIM_ITConfig(TIM5, TIM_IT_CC2, ENABLE);
        NVIC_InitStructure.NVIC_IRQChannel                   = TIM5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
        return 0;
}
回复

使用道具 举报

0

主题

11

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2022-11-29 16:14:16 | 显示全部楼层
eric2013 发表于 2022-11-24 01:14
怎么个用法,CH1,CH2这种通道方式吗,还是互补输出模式。

另外你使用不同的CC中断的话,你要单独开中断 ...

分别触发两个CHN电机运动的函数是:
int motor1_trig(bool dir, uint32_t number, uint32_t freq)
        if (freq != last_freq) {
                last_freq = freq;
                TimerPeriod = ((SystemCoreClock / TIM5_PSC) / freq);
        }

    TIM5->ARR  = (TimerPeriod - 1);
    TIM5->CCR1 = (uint32_t)((TimerPeriod / 2) - 1);
    TIM5->EGR |= TIM_EGR_UG;
    TIM5->CCER = (uint16_t)(TIM_CCER_CC1E);
    TIM5->SR   = 0;
    TIM5->CR1 |= TIM_CR1_CEN;
       
    return 0;
}

int motor2_trig(bool dir, uint32_t number, uint32_t freq)
        if (freq != iris_last_freq) {
                iris_last_freq = freq;
                iris_TimerPeriod = ((SystemCoreClock / TIM5_PSC) / freq);
        }
       
    TIM5->ARR  = (iris_TimerPeriod - 1);
    TIM5->CCR2 = (uint32_t)((iris_TimerPeriod / 2) - 1);
    TIM5->EGR |= TIM_EGR_UG;
    TIM5->CCER = (uint16_t)(TIM_CCER_CC2E);
    TIM5->CR1 |= TIM_CR1_CEN;
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-11-30 10:19:00 | 显示全部楼层
历史的天空 发表于 2022-11-29 16:00
不是互补通道,逻辑上是两个独立的CHN。我确实是单独开的中断,麻烦帮忙看看两个通道的初始化是否有问题 ...

看下了下你的程序配置,你这个是每个CC都进入一次中断,你这个PWM速度快了,中断速度可遭不住,就跟定时器中断控制IO没区别。
回复

使用道具 举报

0

主题

11

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2022-11-30 10:31:04 | 显示全部楼层
eric2013 发表于 2022-11-30 10:19
看下了下你的程序配置,你这个是每个CC都进入一次中断,你这个PWM速度快了,中断速度可遭不住,就跟定时 ...

这个一次性只会触发几个PWM波形,一个PWM对应电机走一步,不会长时间连续执行。
我最大的疑问还是为什么CHN1触发的CCM比较中断,进入中断处理函数时,SR 状态寄存器中 CC1/CC2/CC3/CC4/Upgrade 这5个bit都会被置位??
回复

使用道具 举报

0

主题

11

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2022-11-30 10:34:22 | 显示全部楼层
TIM5的中断处理函数这样实现的:
由于5个bit都被置位,所以必须通过这样的判断条件才能判定到底是那一路CHN触发进入的中断
if (((TIM5->SR & TIM_IT_CC1) == TIM_IT_CC1) && ((TIM5->CCER & TIM_CCER_CC1E) == TIM_CCER_CC1E))

但这样有个问题,就是CHN1和CHN2不能 同时控制,也就是某一个时刻只能让一路CHN工作


void TIM5_IRQHandler(void)
{
    static volatile uint32_t focus_motor_step_counter = 0;
        static volatile uint32_t iris_motor_step_counter  = 0;
   
    if (((TIM5->SR & TIM_IT_CC1) == TIM_IT_CC1) && ((TIM5->CCER & TIM_CCER_CC1E) == TIM_CCER_CC1E)) {
               
        focus_motor_step_counter++;
               
                if (g_Focus_Motor.moving_direction == DIR_to_Far) {
                        g_Focus_Motor.cur_pos++;
                } else if (g_Focus_Motor.moving_direction == DIR_to_Near) {
                        g_Focus_Motor.cur_pos--;
                }

                if (g_Focus_Motor.stage == eMotor_Stage_Searching_PI_Zero) {
                       
                        if (g_Focus_Motor.moving_direction == DIR_to_Far) {
                                if (Get_FOCUS_PI() == 0) {
                                        g_Focus_Motor.stage = eMotor_Stage_Found_PI_Zero;
                                }
                        } else if (g_Focus_Motor.moving_direction == DIR_to_Near) {
                                if (Get_FOCUS_PI() == 1) {
                                        g_Focus_Motor.stage = eMotor_Stage_Found_PI_Zero;
                                }
                        }
                       
                        if (g_Focus_Motor.stage == eMotor_Stage_Found_PI_Zero) {
                                focus_motor_step_counter = 0;
                                g_Focus_Motor.trig_number  = 0;
                                g_Focus_Motor.cur_pos    = 0;
                                TIM5->CR1  &= ((uint16_t)~((uint16_t)TIM_CR1_CEN));
                                TIM5->CCER &= ((uint16_t)~((uint16_t)TIM_CCER_CC1E));
                               
                                g_Focus_Motor.lock = M_UNLOCK;
                        }
                }
                       
               
        if(focus_motor_step_counter >= g_Focus_Motor.trig_number){
            focus_motor_step_counter = 0;
            g_Focus_Motor.trig_number  = 0;
            TIM5->CR1  &= ((uint16_t)~((uint16_t)TIM_CR1_CEN));
            TIM5->CCER &= ((uint16_t)~((uint16_t)TIM_CCER_CC1E));
                       
                        g_Focus_Motor.lock = M_UNLOCK;
        }
               
                if (g_Focus_Motor.stage == eMotor_Stage_Normal_Run) {
                        if (((g_Focus_Motor.cur_pos-1) <= -38 && (g_Focus_Motor.moving_direction == DIR_to_Near))  ||
                                ((g_Focus_Motor.cur_pos+1) >= 80  && (g_Focus_Motor.moving_direction == DIR_to_Far ))) {
                                focus_motor_step_counter = 0;
                                g_Focus_Motor.trig_number  = 0;
                                TIM5->CR1  &= ((uint16_t)~((uint16_t)TIM_CR1_CEN));
                                TIM5->CCER &= ((uint16_t)~((uint16_t)TIM_CCER_CC1E));

                                if (g_Focus_Motor.moving_direction == DIR_to_Near) {
                                        g_Focus_Motor.t_border_protection = eLeft_boundary_protect;
                                } else {
                                        g_Focus_Motor.t_border_protection = eRight_boundary_protect;
                                }
                               
                                g_Focus_Motor.lock = M_UNLOCK;
                        }
                }
    }
       
        if (((TIM5->SR & TIM_IT_CC2) == TIM_IT_CC2) && ((TIM5->CCER & TIM_CCER_CC2E) == TIM_CCER_CC2E)) {
                iris_motor_step_counter++;
               
        if(iris_motor_step_counter >= g_Iris_Motor.trig_number){
            iris_motor_step_counter  = 0;
            g_Iris_Motor.trig_number = 0;
            TIM5->CR1  &= ((uint16_t)~((uint16_t)TIM_CR1_CEN));
            TIM5->CCER &= ((uint16_t)~((uint16_t)TIM_CCER_CC2E));
                       
                        g_Iris_Motor.lock = M_UNLOCK;
        }
        }
   
    TIM5->SR = 0;
}
回复

使用道具 举报

0

主题

11

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2022-11-30 10:36:46 | 显示全部楼层
更新一下完整的Motor 控制函数:

就是在中断中计数,到了预设的控制脉冲个数,就停止

int focus_motor_trig(bool dir, uint32_t number, uint32_t freq)
{
        static int last_dir = -1;
        static uint32_t last_freq = 0;
        static uint32_t TimerPeriod = 0;
       
    if (number == 0) {
        printf("zero trig number\n");
        return -1;
    }
   
    if(freq==0 || freq > 200000){
        printf("invalid freq: %u\n", freq);
        return -1;
    }
       
        if (g_Focus_Motor.lock == M_LOCKED) {
                printf("Focus Motor is busy. trig fail\n");
                return -1;
        }
       
        if (g_Focus_Motor.stage == eMotor_Stage_Normal_Run) {
                if (((g_Focus_Motor.cur_pos-1) <= -38 && (dir == DIR_to_Near))  ||
                        ((g_Focus_Motor.cur_pos+1) >= 80  && (dir == DIR_to_Far ))) {

                        if (g_Focus_Motor.moving_direction == DIR_to_Near) {
                                g_Focus_Motor.t_border_protection = eLeft_boundary_protect;
                        } else {
                                g_Focus_Motor.t_border_protection = eRight_boundary_protect;
                        }
                       
                        //g_Focus_Motor.lock = M_UNLOCK;  //Does not trig motor, no Need Unlock
                        return -3;
                }
        }
       
        g_Focus_Motor.lock             = M_LOCKED;
        g_Focus_Motor.moving_direction = dir;

    if (dir != last_dir) {
                last_dir = dir;
        MDRV_SetABC_Pulse_RT_EN(BU_DEV, CH_Focus, 0, dir, eOut_EN);
    }
   
    g_Focus_Motor.trig_number = number;
       
        if (freq != last_freq) {
                last_freq = freq;
                TimerPeriod = ((SystemCoreClock / TIM5_PSC) / freq);
        }
       
    TIM5->ARR  = (TimerPeriod - 1);
    TIM5->CCR1 = (uint32_t)((TimerPeriod / 2) - 1);
    TIM5->EGR |= TIM_EGR_UG;
    TIM5->CCER = (uint16_t)(TIM_CCER_CC1E);
        TIM5->SR   = 0;
    TIM5->CR1 |= TIM_CR1_CEN;
       
    return 0;
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-12-1 13:56:03 | 显示全部楼层
历史的天空 发表于 2022-11-30 10:31
这个一次性只会触发几个PWM波形,一个PWM对应电机走一步,不会长时间连续执行。
我最大的疑问还是为什么 ...

这个是我们的4通道CC配置。

[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*	函 数 名: bsp_InitHardTimer
*	功能说明: 配置 TIMx,用于us级别硬件定时。TIMx将自由运行,永不停止.
*			TIMx可以用TIM2 - TIM5 之间的TIM, 这些TIM有4个通道, 挂在 APB1 上,输入时钟=SystemCoreClock / 2
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitHardTimer(void)
{
    TIM_HandleTypeDef  TimHandle = {0};
	uint32_t usPeriod;
	uint16_t usPrescaler;
	uint32_t uiTIMxCLK;
	TIM_TypeDef* TIMx = TIM_HARD;
	
	RCC_TIM_HARD_CLK_ENABLE();		/* 使能TIM时钟 */
	
    /*-----------------------------------------------------------------------
		bsp.c 文件中 void SystemClock_Config(void) 函数对时钟的配置如下: 

        System Clock source       = PLL (HSE)
        SYSCLK(Hz)                = 400000000 (CPU Clock)
        HCLK(Hz)                  = 200000000 (AXI and AHBs Clock)
        AHB Prescaler             = 2
        D1 APB3 Prescaler         = 2 (APB3 Clock  100MHz)
        D2 APB1 Prescaler         = 2 (APB1 Clock  100MHz)
        D2 APB2 Prescaler         = 2 (APB2 Clock  100MHz)
        D3 APB4 Prescaler         = 2 (APB4 Clock  100MHz)

        因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = APB1 x 2 = 200MHz;
        因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = APB2 x 2 = 200MHz;
        APB4上面的TIMxCLK没有分频,所以就是100MHz;

        APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
        APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17

        APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5

	----------------------------------------------------------------------- */
	if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15) || (TIMx == TIM16) || (TIMx == TIM17))
	{
		/* APB2 定时器时钟 = 200M */
		uiTIMxCLK = SystemCoreClock / 2;
	}
	else	
	{
		/* APB1 定时器 = 200M */
		uiTIMxCLK = SystemCoreClock / 2;
	}

	usPrescaler = uiTIMxCLK / 1000000 - 1;	/* 分频比 = 1 */
	
	if (TIMx == TIM2 || TIMx == TIM5)
	{
		usPeriod = 0xFFFFFFFF;
	}
	else
	{
		usPeriod = 0xFFFF;
	}

	/* 
       设置分频为usPrescaler后,那么定时器计数器计1次就是1us
       而参数usPeriod的值是决定了最大计数:
       usPeriod = 0xFFFF 表示最大0xFFFF微秒。
       usPeriod = 0xFFFFFFFF 表示最大0xFFFFFFFF微秒。
    */
	TimHandle.Instance = TIMx;
	TimHandle.Init.Prescaler         = usPrescaler;
	TimHandle.Init.Period            = usPeriod;
	TimHandle.Init.ClockDivision     = 0;
	TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
	TimHandle.Init.RepetitionCounter = 0;
    TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
	
	if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
	{
		Error_Handler(__FILE__, __LINE__);
	}

	/* 配置定时器中断,给CC捕获比较中断使用 */
	{
		HAL_NVIC_SetPriority(TIM_HARD_IRQn, 0, 2);
		HAL_NVIC_EnableIRQ(TIM_HARD_IRQn);	
	}
    
    /* 启动定时器 */
	HAL_TIM_Base_Start(&TimHandle);
}

/*
*********************************************************************************************************
*	函 数 名: bsp_StartHardTimer
*	功能说明: 使用TIM2-5做单次定时器使用, 定时时间到后执行回调函数。可以同时启动4个定时器通道,互不干扰。
*             定时精度正负1us (主要耗费在调用本函数的执行时间)
*			  TIM2和TIM5 是32位定时器。定时范围很大
*			  TIM3和TIM4 是16位定时器。
*	形    参: _CC : 捕获比较通道几,1,2,3, 4
*             _uiTimeOut : 超时时间, 单位 1us. 对于16位定时器,最大 65.5ms; 对于32位定时器,最大 4294秒
*             _pCallBack : 定时时间到后,被执行的函数
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void * _pCallBack)
{
    uint32_t cnt_now;
    uint32_t cnt_tar;
	TIM_TypeDef* TIMx = TIM_HARD;
	
    /* H743速度较快,无需补偿延迟,实测精度正负1us */
    
    cnt_now = TIMx->CNT; 
    cnt_tar = cnt_now + _uiTimeOut;			/* 计算捕获的计数器值 */
    if (_CC == 1)
    {
        s_TIM_CallBack1 = (void (*)(void))_pCallBack;

		TIMx->CCR1 = cnt_tar; 			    /* 设置捕获比较计数器CC1 */
        TIMx->SR = (uint16_t)~TIM_IT_CC1;   /* 清除CC1中断标志 */
		TIMx->DIER |= TIM_IT_CC1;			/* 使能CC1中断 */
	}
    else if (_CC == 2)
    {
		s_TIM_CallBack2 = (void (*)(void))_pCallBack;

		TIMx->CCR2 = cnt_tar;				/* 设置捕获比较计数器CC2 */
        TIMx->SR = (uint16_t)~TIM_IT_CC2;	/* 清除CC2中断标志 */
		TIMx->DIER |= TIM_IT_CC2;			/* 使能CC2中断 */
    }
    else if (_CC == 3)
    {
        s_TIM_CallBack3 = (void (*)(void))_pCallBack;

		TIMx->CCR3 = cnt_tar;				/* 设置捕获比较计数器CC3 */
        TIMx->SR = (uint16_t)~TIM_IT_CC3;	/* 清除CC3中断标志 */
		TIMx->DIER |= TIM_IT_CC3;			/* 使能CC3中断 */
    }
    else if (_CC == 4)
    {
        s_TIM_CallBack4 = (void (*)(void))_pCallBack;

		TIMx->CCR4 = cnt_tar;				/* 设置捕获比较计数器CC4 */
        TIMx->SR = (uint16_t)~TIM_IT_CC4;	/* 清除CC4中断标志 */
		TIMx->DIER |= TIM_IT_CC4;			/* 使能CC4中断 */
    }
	else
    {
        return;
    }
}

/*
*********************************************************************************************************
*	函 数 名: TIMx_IRQHandler
*	功能说明: TIM 中断服务程序
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void TIM_HARD_IRQHandler(void)
{
	uint16_t itstatus = 0x0, itenable = 0x0;
	TIM_TypeDef* TIMx = TIM_HARD;
	
    
  	itstatus = TIMx->SR & TIM_IT_CC1;
	itenable = TIMx->DIER & TIM_IT_CC1;
    
	if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
	{
		TIMx->SR = (uint16_t)~TIM_IT_CC1;
		TIMx->DIER &= (uint16_t)~TIM_IT_CC1;		/* 禁能CC1中断 */	

        /* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
        s_TIM_CallBack1();
    }

	itstatus = TIMx->SR & TIM_IT_CC2;
	itenable = TIMx->DIER & TIM_IT_CC2;
	if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
	{
		TIMx->SR = (uint16_t)~TIM_IT_CC2;
		TIMx->DIER &= (uint16_t)~TIM_IT_CC2;		/* 禁能CC2中断 */	

        /* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
        s_TIM_CallBack2();
    }

	itstatus = TIMx->SR & TIM_IT_CC3;
	itenable = TIMx->DIER & TIM_IT_CC3;
	if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
	{
		TIMx->SR = (uint16_t)~TIM_IT_CC3;
		TIMx->DIER &= (uint16_t)~TIM_IT_CC3;		/* 禁能CC2中断 */	

        /* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
        s_TIM_CallBack3();
    }

	itstatus = TIMx->SR & TIM_IT_CC4;
	itenable = TIMx->DIER & TIM_IT_CC4;
	if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
	{
		TIMx->SR = (uint16_t)~TIM_IT_CC4;
		TIMx->DIER &= (uint16_t)~TIM_IT_CC4;		/* 禁能CC4中断 */	

        /* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
        s_TIM_CallBack4();
    }	
}

#endif
回复

使用道具 举报

0

主题

11

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2022-12-1 19:31:09 | 显示全部楼层
感谢硬汉,我自己对照一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-15 14:23 , Processed in 0.196393 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表