zoukankan      html  css  js  c++  java
  • 关于C51的中断函数要注意的几个问题

    原文链接:http://blog.csdn.net/cwybruce/article/details/8191483

    关于C51的中断函数要注意的几个问题(高手绕行)

        最近在虾潭逛,发现一些小虾米对C51中断函数有些不了解,今天周末,抽空发个技术帖子,希望对小虾米有所帮助,如有错误之处,还请指正,就当抛砖引玉吧!

        C51的中断函数的格式为:

        void FuncIr(void) interrupt x [using y]

        以下是梦游的一些分析:

        一、中断函数是一个特殊的函数,没有参数,也没有返回值;但是程序中允不允许使用return呢?答案是允许的,不过只能用"return;",不能用"return(z);";用在一些需要快速返回的地方,对应的汇编会有多个ret语句,相对效率会高一些。

        二、using的用法,using可以修饰任何函数,不过个人建议只用来修饰中断函数;简单的说,“using”会指定工作寄存器组,由于中断函数一般都是比较紧急的事情,有时一条语句都会斤斤计较,所以使用using切换寄存器组可以省去一些压栈的动作,由于51只有两级中断,同级中断不能被打断,因此,我们可以同级中断设成同样的寄存器组,从某种意义上来说,有一组寄存器是多余的。同时个人建议中断函数应该使用using这个关键字。

        三、中断中调用函数,首先要讨论中断函数中调用函数的必要性,前天在论坛上我和别人争论过这个问题,现在我还是这个观点:有些情况中断中调用函数还是必要的,这个时候是不是该调用函数,其实和普通函数差不多,首先是这个函数如果调用多次,或者要带一些参数什么的就更加必要的;前天有人跟我叫劲,说假如只调用一次且无参数无返回的函数要直接写,因为如果用函数,至少会增加CALL和RET两条语句,我不敢苟同,我是实际调试发现的,当你程序比较复杂时,你将那部分单独拉出来做成函数,可能代码和时间都会更好

        四、中断中调用的函数最好不要被中断外的其它函数调用,因为会出现“重复调用”的警告,有时这种调用是很致命的,有人说这个函数可以用reentrant来修饰,是的,的确可以这样解决,不过个人不建议这么做,也许这样会跟你减少很多堆栈空间,并且整个程序的优化要差很多,个人建议出现这种情况就把这个函数写两遍,分成两个函数分别调用。

        五,中断调用了函数,会出现一些莫名其妙的问题,一些数据不对。其实一般是因为汇编中使用了绝对寄存器引起的,有人说中断函数使用那个寄存器组,被中断调用的

    函数就使用哪个寄存器组,我认为这样不好:

        这样会增加额外的消耗,使用using会增加一下语句:

        PUSH PSW

        MOV PSW, #XX

        ....

        POP PSW

       更重要的是,使用using的函数不能有返回值,这是致命伤

       个人推荐的方法有两种:

       1、使用“#pragma NOAREGS”禁止使用绝对寄存器

       2、使用“#pragme RB(x)”来指定本文件的工作寄存器组

       六、一般说来,要求中断函数尽可能的短,但也有特殊情况,有些前/后台的系统中,就会把很多相对重要的事情放到定时中断(这个定时中断类似实时操作系统中的时钟节拍)去做,而且程序很长。我单独提出来这点是想告诉大家,中断函数也是一个函数而已,只要系统有必要,可以做一些看似不合理的事情,该出手时就出手,就像goto语句一样。

     

     

    51单片机的中断函数

     

     

    中断使用interrupt 关键字和中断编号0-4来实现:

    返回值 函数名 interrupt n

    n对应中断源的编号,中断编号告诉中断器中断程序的入口地址,它对应着IE寄存器中的使能位,即IE寄存器中的0位对应着外部中断0。

    8051单片机的中断源以及终端编号如下:

    中断编号   中断源                             入口地址

     0            外部中断0                          0003H 

    1             定时器/计数器0 溢出         000BH 

    2             外部中断1                           0013H 

    3             定时器/计数器1 溢出         001BH 

    4              串行口中断                 0023H

     

    在51系列单片机中,有的单片机多达32个中断源,所以中断编号是0-31.当正在执行一个特定的任务时,可能有更紧急的事情需要CPU处理,这就涉及到了中断优先级。高优先级中断可以中断正在处理的低优先级中断程序,因而最好给每种优先级程序分配不同的寄存器组。在C51中可使用using指定寄存器组,using后的变量为0-3的常整数,分别表示51单片机内的4哥寄存器组。中断函数的完整语法如下:

    返回值 函数名([参数])[模式][重入]interrupt n[usingn]

    unsigned int interruptcnt;

    unsigned char second;

    void timer0(void) interrupt 1 using 2

    if(++interruptcnt==4000) // 计数到4000

    second++; //另一个计数器

    interruptcnt=0; //计数器清零

  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/hubery/p/3156258.html
Copyright © 2011-2022 走看看