STM32F407定时器溢出中断问题——进入中断次数异常

在STM32F407上使用定时器3产生1ms定时中断,timer3初始化代码如下:

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);             //使能TIM3时钟

    TIM_TimeBaseInitStructure.TIM_Period = arr;                     //自动重装载值
    TIM_TimeBaseInitStructure.TIM_Prescaler=psc;                    //定时器分频
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;   //向上计数模式
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 

    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);              //初始化TIM3

    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);                        //允许定时器3更新中断
    TIM_Cmd(TIM3,ENABLE);                                           //使能定时器3

    NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;                   //定时器3中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;      //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;             //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

初始化1ms定时中断:

TIM3_Int_Init(10-1,8400-1);     //定时器时钟84M,分频系数8400,所以84M/8400=10Khz的计数频率,计数10次为1ms   

timer3定时中断服务程序:

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
    {
        Key_Counter();                          //按键扫描延时操作
    }

    LED_Out = !LED_Out
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}

通过LED闪烁频率,验证中断频率设置是否正确。然而……

这里写图片描述
系统上电后,示波器观察到的LED管脚波形,频率1KHz,占空比99%(正常应为500Hz,占空比50%)。
这里写图片描述
LED低电平脉宽只有560ns。

这里写图片描述
系统重新复位后,示波器观察到的LED管脚波形,频率1KHz,占空比小于1%(正常应为500Hz,占空比50%)。

这里写图片描述
这下LED高电平脉宽只有约560ns。

不断试验,中断代码做如下更改:

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
    {
        Key_Counter();                          //按键扫描延时操作
    }

    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
    LED_Out = !LED_Out;
}

即先清除中断,再输出LED,波形输出如下:
修改代码后,LED引脚正常波形
修改代码后,LED引脚正常波形。

问题虽然解决了,但是目前仍然不知道造成该问题的最终原因。
待后续发现……

网上找到两个类似的问题:
关于STM32F407的定时器中断的诡异问题
STM32F407 定时器TIM3 出现

### STM32F407 TIM9 定时器中断使用教程 #### 初始化设置 为了初始化并配置 TIM9 的定时器中断,需先通过 CubeMX 或手动编写代码来完成硬件资源分配。TIM9 是一个通用定时器,在 STM32F4系列中有其特定的功能和寄存器。 ```c // 配置 TIM9 时钟源及时基分频系数等参数 static void MX_TIM9_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim9.Instance = TIM9; htim9.Init.Prescaler = 8399; // 设置预分频值 htim9.Init.CounterMode = TIM_COUNTERMODE_UP; htim9.Init.Period = 999; // 自动重装载值 htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim9.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim9) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim9, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } } ``` #### 启用定时器中断 启用 TIM9 更新事件触发的中断请求,并启动计数过程: ```c if (HAL_TIM_Base_Start_IT(&htim9) != HAL_OK) { Error_Handler(); // 错误处理函数 } __HAL_TIM_ENABLE_IT(&htim9, TIM_IT_UPDATE); ``` 上述操作会激活 TIM9 的更新中断[^2]。 #### 中断服务程序 当发生定时溢出时,CPU 将跳转到对应的中断向量表位置执行相应的 ISR(Interrupt Service Routine)。对于 TIM9 来说,默认情况下该ISR名为 `TIM1_BRK_TIM9_IRQHandler`: ```c void TIM1_BRK_TIM9_IRQHandler(void) { if (__HAL_TIM_GET_FLAG(&htim9, TIM_FLAG_UPDATE) != RESET && __HAL_TIM_GET_IT_SOURCE(&htim9, TIM_IT_UPDATE) != RESET) { // 清除标志位以防再次进入中断 __HAL_TIM_CLEAR_IT(&htim9, TIM_IT_UPDATE); // 用户自定义的任务逻辑... } } ``` 这段代码展示了如何检测是否确实发生了由 TIM9 引发的更新中断以及清除相应状态以便后续正常工作[^3]。 #### 实现周期性回调函数 如果项目基于 HAL 库开发,则可以利用 HAL 提供的钩子机制实现更简洁的方式管理定时任务——即覆写默认的 `HAL_TIM_PeriodElapsedCallback()` 函数来进行定制化响应动作: ```c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM9) { // 处理与 TIM9 相关的时间片到期后的业务逻辑 } } ``` 这样做的好处是可以让多个外设共享同一个物理中断线路上的不同时间间隔下的不同行为而无需频繁切换上下文环境[^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值