interrupt和using在C51中断中的使用

发布者:等放假的zr0最新更新时间:2015-10-13 来源: eefocus关键字:interrupt  using  C51中断 手机看文章 扫描二维码
随时随地手机看文章
C51的中断函数的格式为:void FuncIr(void) interrupt x [using y]

interrupt和using都是C51的关键字。C51中断过程通过使用interrupt关键字和中断号(0到3)来实现,中断号指明了中断程序的入口地址。有了这一声明,编译器不需理会寄存器组参数的使用和对累加器A、状态寄存器、寄存器B、数据指针和默认的寄存器的保护。只要在中断程序中用到,编译器会把它们压栈,在中断程序结束时将他们出栈。C51支持所有5个8051标准中断(从0到4)和在8051系列(增强型)中多达27个的中断源。

using关键字用来指定中断服务程序使用的寄存器组。用法是:using后跟一个0到3的数,对应着 4组工作寄存器。一旦指定工作寄存器组,默认的工作寄存器组就不会被压栈,这将节省32个处理周期,因为入栈和出栈都需要2个处理周期。这一做法的缺点是所有调用中断的过程都必须使用指定的同一个寄存器组,否则参数传递会发生错误。因此对于using,在使用中需灵活取舍。

如果在ISR(中断服务函数)中使用寄存器,那么必须处理好using的使用问题:

1、中断服务函数使用using指定与主函数不同的寄存器组(主函数一般使用 Register bank 0)。

2、中断优先级相同的ISR可用using指定相同的寄存器组,但优先级不同的ISR必须使用不同的寄存器组,在ISR中被调用的函数也要使用using指定与中断函数相同的寄存器组。

3、如果不用using指定,在ISR的入口,C51 默认选择寄存器组0,这相当于中断服务程序的入口首先执行指令:MOV PSW #0

这点保证了,没使用using指定的高优先级中断。可以中断使用不同的寄存器组的低优先级中断。

4、使用using关键字给中断指定寄存器组,这样直接切换寄存器组而不必进行大量的 PUSH和POP操作,可以节省RAM空间,加速 MCU 执行时间。寄存器组的切换,总的来说比较容易出错,要对内存的使用情况有比较清晰的认识,其正确性要由你自己来保证。特别在程序中有直接地址访问的时候,一定要小心谨慎!至于“什么时候要用到寄存器组切换”,一种情况是:当你试图让两个(或以上)作业同时运行,而且它们的现场需要一些隔离的时候,就会用上了。在ISR或使用实时操作系统RTOS中,寄存器非常有用。

 

寄存器组使用的原则:

1、8051的最低32个字节分成4组8寄存器。分别为寄存器R0到R7。寄存器组由PSW 的RS1(PSW^4)、RS0(PSW^3)两位选择。在ISR中,MCU可以切换到一个不同的寄存器组。对寄存器的访问不可位寻址,C51编译器规定使用using或禁止中断的函数(#pragma disable)均不能返回bit类型的值。

2、主程序(main函数)使用一组,如 bank 0;低中断优先级的所有中断均使用第二组,如bank 1;高中断优先级的所有中断均使用另外一组,如 bank 2。显然,同级别的中断使用同一组寄存器不会有问题,因为不会发生中断嵌套;而高优先级的中断则要使用与低优先级中断不同的一组,因为有可能出现在低优先级中断中发生高优先级中断的情况。编译器会自动判断何时可使用绝对寄存器存取。

3、在ISR中调用其它函数,必须和中断使用相同的寄存器组。当没用NOAREGS命令做明确的声明,编译器将使用绝对寄存器寻址方式访问函数选定(即用using或REGISTERBANK指定)的寄存器组,当函数假定的和实际所选的寄存器组不同时,将产生不可预知的结果,从而可能出现参数传递错误,返回值可能会在错误的寄存器组中。

举一例子:当需要在中断内和中断外调用同一个函数,假定按照程序的流程控制,不会出现函数的递归调用现象,这样的调用会不会出现问题?若确定不会发生重入情况,则有以下两种情况:

1、如果ISR和主程序使用同一寄存器组(主程序缺省使用BANK 0,若ISR没有使用using为其指定寄存器区,则缺省也使用BANK 0),则不需其他设置。

2、如果 ISR 和主程序使用不同的寄存器组(主程序缺省使用BANK 0,ISR使用using指定了其他BANK),则被调用函数必须放在:#pragma NOAREGS和#pragma AREGS控制参数对中,指定编译器不要对该函数使用绝对寄存器寻址方式;或者也可在 Options->C51,选中“Don't use absolute register accesses”,使所有代码均不使用绝对寄存器寻址方式(这样,执行效率将稍有降低)。不论以上的哪一种情况,编译器均会给出重入警告,需手工更改OVERLAY参数,做重入说明。

3、还有一种办法:如果被调用函数的代码不是很长,还是将该函数复制一份,用不同的函数名代替,这种情况适合ROM有足够多余的空间。

因此,对using关键字的使用,如果没把握,宁可不用,交给编译系统自己去处理好了。

————————————————————————————————

以下是梦游的一些分析:

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

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

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

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

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

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

   PUSH PSW

   MOV PSW, #XX

    ....

   POP PSW

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

个人推荐的方法有两种:

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

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

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

关键字:interrupt  using  C51中断 引用地址:interrupt和using在C51中断中的使用

上一篇:STARTUP.A51注解
下一篇:基于proteus的步进电机控制

推荐阅读最新更新时间:2024-03-16 14:35

C51单片机中断定义
C51函数声明对ANSI C作了扩展,具体包括: 1. 中断函数声明: 中断声明方法如下: void serial_ISR () interrupt 4 { /* ISR */ } 为提高代码的容错能力,在没用到的中断入口处生成iret语句,定义没用到的中断。 /* define not used interrupt, so generate IRET in their entrance */ void extern0_ISR() interrupt 0{} /* not used */ void timer0_ISR () interrupt 1{} /* not used */ void extern1_ISR()
[单片机]
出现“Unable to create configuration 'Debug' using tool chain ‘STM8’
用IAR打开STM8时,出现“Unable to create configuration 'Debug' using tool chain ‘STM8’, 出现这个问题的原因是按装的IAR不正确,要装ST for STM8 版本的,而不能用ST for ARM版本的 ST for ARM图标 ST for STM8 图标
[单片机]
出现“Unable to create configuration 'Debug' <font color='red'>using</font> tool chain ‘STM8’
C51/C52单片机的中断(EXTI)介绍(一)
一、什么是中断 打断:打断当前做的事情,去执行中断函数里的程序,执行完过后回来接着执行原来未执行完的程序。如下图所示: 二、中断源及中断号 注意:写中断服务函数时,中断源与中断号要一一对应,否则不能进入中断服务函数,比如: void Timer0IRQ(void) interrupt 1 //1就是中断号,默认工作组0 格式如下: void 函数名(void) interrupt 中断号 using 工作组 { 中断服务函数内容; } 三、中断相关寄存器介绍 1、中断允许控制寄存器IE 2、扩展中断控制寄存器XICON(STC89C52RC) 四、中断优先级
[单片机]
<font color='red'>C51</font>/C52单片机的<font color='red'>中断</font>(EXTI)介绍(一)
C51程序设计中断及寄存器使用方法
如果在中断服务函数ISR中使用寄存器,那么必须处理好using的使用问题: 1、中断服务函数使用using指定与主函数不同的寄存器组(主函数一般使用Register bank 0)。 2、中断优先级相同的ISR可用using指定相同的寄存器组,但优先级不同的ISR必须使用不同的寄存器组,在ISR中被调用的函数也要使用using指定与中断函数相同的寄存器组。用reentranr指明可重入函数。 3、如果不用using指定,在ISR的入口,C51默认选择寄存器组0,这相当于中断服务程序的入口首先执行指令: MOV PSW #0 这点保证了,没使用using指定的高优先级中断。可以中断使用不同的寄存器组的低优先级中断。 4、使用usin
[单片机]
U-Boot移植(13)Warning - bad CRC or NAND, using default environment
接上面(5)在串口终端出现如下: U-Boot 1.1.6 (Nov 25 2009 - 22:15:51) DRAM: 64 MB Flash: 1 MB NAND: 64 MiB *** Warning - bad CRC, using default environment 还存在警告,这个警告不是错误,而是新的环境变量起作用, 只要在OPENJTAG 下输入saveenv就能保存新的环境变量,reset之后就可以看到Warning消失了。。。 但是我在下面输入saveenv、reset之后还存在警告。。。 网友henry.li说:估计是你的环境变量保存的位置不正确,环境变量实际上没有保存。 我想想还是很有道理的,否则
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved