这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 51单片机中断心得整理(转)

共4条 1/1 1 跳转至

51单片机中断心得整理(转)

高工
2009-02-14 17:10:01     打赏
51单片机中断心得整理 技术分类: 微处理器与DSP  | 2009-02-13
作者:shao_gu: EDN China

  EDN博客精华文章  作者:shao_gu

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

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

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

  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 的低两位选择。在 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,选中“Dont use absolute register accesses”,使所有代码均不使用绝对寄存器寻址方式(这样,执行效率将稍有降低)。不论以上的哪一种情况,编译器均会给出重入警告,需手工更改 OVERLAY 参数,做重入说明。

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

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

  #pragma disable

  在函数前声明,只对一个函数有用,该函数调用过程中,将不可被中断。

  递归或可重入函数指定

  在主程序和中断程序都调用的函数容易出现问题,用寄存器传递参数,内部变量在RAM中,函数重入时候,会破坏上次的数据,用下面两种方法解决函数重入问题:

  在相应的函数前,加“#pragma disable”声明,只允许主程序或者中断之一调用该函数;

  将该函数说明为可重入:VOID func(para..) reentrant;

  指定存储模式

  由small compact 及large 说明,例如:

  void fun1(void) small { }

  提示:small 说明的函数内部变量全部使用内部RAM。关键的经常性的耗时的

  地方可以这样声明,以提高运行速度。




关键词: 单片机     中断     心得     整理     函数     使用     寄存器     us    

高工
2009-02-20 09:44:09     打赏
2楼
讲得不错,看了挺有收获的

助工
2009-02-21 13:40:18     打赏
3楼

中断感觉一直很难理解,看来要下大功夫才行


菜鸟
2009-02-25 16:16:43     打赏
4楼
讲的很好

共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]