[STM32F4] 关于HAL库外部中断进两次中断服务的问题

[复制链接]
2604|25
 楼主| 数码小叶 发表于 2020-6-18 10:46 | 显示全部楼层 |阅读模式
本帖最后由 数码小叶 于 2020-6-18 10:52 编辑

最近一个应用里用到了STM32F4的两个外部中断,但是最终结果一直不对,发现仿真是正确的,单独运行就不正确,多次调试后发现问题出现在中断上,中断服务函数进了两次,但是这个应用只允许进一次中断
在论坛搜索到两个帖子:


用HAL库写的一个STM32的中断程序,为什么会发生两次中断
https://bbs.21ic.com/icview-2520878-1-1.html?fromuser=
(出处: 中国电子网技术论坛)

关于STM32中断多进的问题总结
https://bbs.21ic.com/icview-184728-1-1.html?fromuser=
(出处: 中国电子网技术论坛)


知道了问题出现的原因是AHB2APB桥延迟,其中提到几条建议:
1)进入中断后,判断了相应标志位,就clear之,在作后续的处理
3、解决方法:清中断标志,只要不是中断函数的最后一条语句就没问题了。
当前这个情况下把程序下载到板子上运行的时候,按下按键,LED的状态会翻转两次,后来尝试改了一下软件生成的代码,将清中断标志位那条语句放到调用中断回调函数之后就可以了



程序原本的代码:


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{  
        if(GPIO_Pin == GPIO_PIN_8)
        {
                xxxxxxxxxxxxxxxxxxxxxxxxx;

        }
}


原本的清标志是自动生成的


void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}




按照建议,改成如下依旧无效果


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{  
       __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
        if(GPIO_Pin == GPIO_PIN_8)
        {
                xxxxxxxxxxxxxxxxxxxxxxxxx;

        }
}


void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
   __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
  }
}








598330983 发表于 2020-6-18 19:06 | 显示全部楼层
官方的例子中这个操作是怎么实现的
598330983 发表于 2020-6-18 19:13 | 显示全部楼层
好奇怪啊,安装官方原本的方法就行啊。
598330983 发表于 2020-6-18 19:17 | 显示全部楼层
39405eeb4d509cfc3.png
是不是因为没有放到这个里面
598330983 发表于 2020-6-18 19:19 | 显示全部楼层
697455eeb4db712a96.png
因为在启动文件里是这样进入中断的。
 楼主| 数码小叶 发表于 2020-6-18 20:58 | 显示全部楼层
598330983 发表于 2020-6-18 19:19
因为在启动文件里是这样进入中断的。

没有明白你的意思,可以讲解一下问题出在哪么,这个卡好久了
598330983 发表于 2020-6-18 22:18 | 显示全部楼层
数码小叶 发表于 2020-6-18 20:58
没有明白你的意思,可以讲解一下问题出在哪么,这个卡好久了 ...

你看一下官方的例子就明白了。还有启动文件,中断要放到中短线函数里,才能起效。
598330983 发表于 2020-6-18 22:23 | 显示全部楼层
void EXTI4_15_IRQHandler(void)
{
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
}

这样就可以了。
 楼主| 数码小叶 发表于 2020-6-19 08:46 | 显示全部楼层
598330983 发表于 2020-6-18 22:23
void EXTI4_15_IRQHandler(void)
{
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);

这个代码程序里有啊,不是进不去中断,是一次中断,会跳转两次到中断服务程序
598330983 发表于 2020-6-22 22:20 | 显示全部楼层
数码小叶 发表于 2020-6-19 08:46
这个代码程序里有啊,不是进不去中断,是一次中断,会跳转两次到中断服务程序 ...

那就不清楚啥情况了,还没解决?》
598330983 发表于 2020-6-22 22:21 | 显示全部楼层
是不是真滴发生了两次,按键抖动了?
sonicll 发表于 2020-6-23 08:50 | 显示全部楼层
你在EXTI4_15_IRQHandler里面先清中断标志看看,这里是中断最早执行的地方
 楼主| 数码小叶 发表于 2020-6-23 09:08 | 显示全部楼层
598330983 发表于 2020-6-22 22:21
是不是真滴发生了两次,按键抖动了?

确确实实是进入两次,HAL_GPIO_EXTI_IRQHandler进入一次,HAL_GPIO_EXTI_Callback进入两次,一进HAL_GPIO_EXTI_IRQHandler就关闭中断,HAL_GPIO_EXTI_Callback依旧两次
 楼主| 数码小叶 发表于 2020-6-23 09:13 | 显示全部楼层
sonicll 发表于 2020-6-23 08:50
你在EXTI4_15_IRQHandler里面先清中断标志看看,这里是中断最早执行的地方

醉了,这样居然真的可以达到效果,但是判断中断操作居然在清标志之后,不过好像也可以讲得通
labasi 发表于 2020-7-9 14:07 | 显示全部楼层
我印象中并不需要手动清除标志位啊
paotangsan 发表于 2020-7-9 14:07 | 显示全部楼层
用示波器看看实际上是不是产生了两个中断信号呢
renzheshengui 发表于 2020-7-9 14:07 | 显示全部楼层
没遇到过这个问题
wakayi 发表于 2020-7-9 14:08 | 显示全部楼层
帮楼主顶一下
wowu 发表于 2020-7-9 14:08 | 显示全部楼层
楼主解决问题了吗

评论

解决了  发表于 2020-7-9 15:59
 楼主| 数码小叶 发表于 2020-7-9 16:01 | 显示全部楼层
paotangsan 发表于 2020-7-9 14:07
用示波器看看实际上是不是产生了两个中断信号呢

我是一进去就关中断了,根本原因是清中断时间不够
您需要登录后才可以回帖 登录 | 注册

本版积分规则

105

主题

2560

帖子

19

粉丝
快速回复 在线客服 返回列表 返回顶部