打印
[MCU]

中断处理函数太长了吗?

[复制链接]
2547|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
拨云人|  楼主 | 2014-4-16 09:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 拨云人 于 2014-4-16 11:35 编辑

主要问题:大家经常说,中断处理函数不要执行时间太长,  但我现在的工程本身是一个事件触发的系统,主程序只完成了一些初始化功能,然后就进入了睡眠并等待事件的发生(sleep and  wait for event), 几乎所有要执行的功能,都是在中断里完成的,甚至在中断里调用了软件延时100ms   ( delay_ms(100) )  这样的函数.
会不会造成一些不良后果呢?

有三个GPIO中断源,一个蓝牙协议栈中断,
系统可简述为3个模块: 采集模块存储模块(SD卡),BLE蓝牙模块
GPIO中断可分为:
1、 由采集芯片产生, 每4ms 产生一次,在中断处理函数里,我只是做了接收数据(通过SPI),并置了各种标志位.
2、 按键中断, 检测到按键按下之后,需要处理很多事情,例如 SD卡初始化,采集芯片初试化等,这个耗时会比较长.但是正常情况下,正在采集的时候,是把按键功能关闭的。
3、 外部高电平中断,当检测到USB线的插入时,会在某个引脚检测到高电平,这时候我需要给SD卡重新上电,也就是在这里调用了 delay_ms(100),这个中断处理过程也会很长。

中断2,3的处理时间都很长,但是正常情况下,如果正在采集(中断源1使能),那么中断源 2,3,都是处于关闭状态的。只有结束采集之后,才会打开。

在中断1的处理函数中,会根据接收到的数据,以及进入中断的次数,置很多的标志位.然后我的主循环就成了:
while(1)
{
    sleep();    //每次从中断回来,都会往下执行一遍
    if(xxx_flag==1)
     {
         xxx_flag= 0;
         do_someting;
     }; // 检测到某标志位,后..

    if(xxx_flag==1)
     {
         xxx_flag= 0;
         do_someting;
     }; // 检测到另一个标志位后...  

    if(xxx_flag==1)
     {
          xxx_flag= 0;
          do_someting;
     };// 检测到另一个标志位后...   
     ...
     ...
     ...
}
这样的结构,我都不忍直视了.:'(
















相关帖子

沙发
anne82820| | 2014-4-16 09:42 | 只看该作者
如果说你没有其他的中断的,其他程序时间或者优先级什么要求都不高的话,是可以的。但是最好在中断程序中不要做太多的工作的。可以搞个标志位,一些处理工作在主程序中做的

使用特权

评论回复
板凳
sonicll| | 2014-4-16 09:49 | 只看该作者
最好是中断处理函数里只设置标志位,然后主循环里检查标志位再处理事件

使用特权

评论回复
地板
ayb_ice| | 2014-4-16 10:08 | 只看该作者
如果有多个中断就不好

使用特权

评论回复
5
wjt_tyy| | 2014-4-16 10:11 | 只看该作者
楼主睡眠是为了低功耗?

使用特权

评论回复
6
aozima| | 2014-4-16 10:42 | 只看该作者
中断处理函数不要执行时间太长

这个“太长”到底是多长没人定义,一般视具体情况而定。
类似变频器的应用,可能整个ISR占了90%以上的CPU时间都是有可能的。

不过从楼主的ISR中有delay(100)来说只能说“呵呵”了

使用特权

评论回复
7
拨云人|  楼主 | 2014-4-16 11:31 | 只看该作者
本帖最后由 拨云人 于 2014-4-16 11:33 编辑
ayb_ice 发表于 2014-4-16 10:08
如果有多个中断就不好

有三个GPIO中断源,一个蓝牙协议栈中断,
系统可简述为3个模块: 采集模块存储模块(SD卡),BLE蓝牙模块
GPIO中断可分为:
1、 由采集芯片产生, 每4ms 产生一次,在中断处理函数里,我只是做了接收数据(通过SPI),并置了各种标志位.
2、 按键中断, 检测到按键按下之后,需要处理很多事情,例如 SD卡初始化,采集芯片初试化等,这个耗时会比较长.但是正常情况下,正在采集的时候,是把按键功能关闭的。
3、 外部高电平中断,当检测到USB线的插入时,会在某个引脚检测到高电平,这时候我需要给SD卡重新上电,也就是在这里调用了 delay_ms(100),这个中断处理过程也会很长。

中断2,3的处理时间都很长,但是正常情况下,如果正在采集(中断源1使能),那么中断源 2,3,都是处于关闭状态的。只有结束采集之后,才会打开。

在中断1的处理函数中,会根据接收到的数据,以及进入中断的次数,置很多的标志位.然后我的主循环就成了:
while(1)
{
        sleep();    //每次从中断回来,都会往下执行一遍
        if(xxx_flag==1)
         {
                 xxx_flag= 0;
                 do_someting;
         }; // 检测到某标志位,后..

        if(xxx_flag==1)
         {
                 xxx_flag= 0;
                 do_someting;
         }; // 检测到另一个标志位后...  

        if(xxx_flag==1)
         {
                 xxx_flag= 0;
                 do_someting;
         };// 检测到另一个标志位后...   
        ...
        ...
        ...
}
这样的结构,我都不忍直视了.:'(




使用特权

评论回复
8
ayb_ice| | 2014-4-16 11:35 | 只看该作者
长延时不是一定不可以

但肯定影响实时性,比如在高优先级中延时,低优先级的中断都会被屏蔽了,主循环就更不说了

到底可不可行,要看具体需要了

使用特权

评论回复
9
justsuperone| | 2014-4-16 12:52 | 只看该作者
我这里插一句那个定时器里面可不可以放些执行程序啊

使用特权

评论回复
10
dirtwillfly| | 2014-4-16 17:29 | 只看该作者
建议不要在中断里使用类似delay_ms(100)的延时。
可以采用定时器方式延时,等待的时候进入休眠

使用特权

评论回复
11
通宵敲代码| | 2014-4-16 21:32 | 只看该作者
处理好中断优先级,只要不会造成数据丢失或是死机,这样也可以。

使用特权

评论回复
12
湖北泽翔| | 2014-4-16 22:12 | 只看该作者

使用特权

评论回复
13
湖北泽翔| | 2014-4-16 22:12 | 只看该作者

使用特权

评论回复
14
湖北泽翔| | 2014-4-16 22:12 | 只看该作者

使用特权

评论回复
15
liuxin198405| | 2014-4-17 09:08 | 只看该作者
最好是中断处理函数里只设置标志位,然后主循环里检查标志位再处理事件

使用特权

评论回复
16
zhangwenbin| | 2014-4-17 09:56 | 只看该作者
  中断设定标志位就好了,其他放主程序主程序跑,又标志位则运行,无则不运行

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

34

帖子

0

粉丝