最近在基于51单片机编程的过程中出现了个很奇怪的问题“程序执行中在寄存器EA=1,ET0=1,TR0=1条件下,单TF0=1时并没有执行中断”。在有过单片机中断编程经历者都知道当EA=1,ET0=1的条件下,满足TF0=1时,如果在此期间没有更高优先级的中断执行的情况下定时器中断0必定会产生中断响应。而在我所编写的程序中仅使用了定时器中断0,一个中断也就谈不上存在优先级问题。经过我对自己程序的检查并对各教材中断程序对比发现我的程序中的一个问题:由于中断的不可控性决定其跳出中断返回主程序的不确定,而由于程序需要中断跳出后能跳到指定的地址。为了解决这个问题我在中断结束的地方直接用了无条件跳转指令“LJMPADR16”其中ADR16是我想在中断结束后程序所运行的地址,而没有经过指令“RETI”。问题找到了这就意味着我的程序和其他程序不同的地方就是没有执行“RETI”而直接跳出。

  为了解决问题所在我查阅了很多单片机方面的资料,教材。几乎所有的教材对指令“RETI”的作用千篇一律都是:“中断程序完成后,一定要执行一条RETI指令,执行这条指令后,CPU将会把堆栈中保存着的地址取出,送回PC,那么程序就会从主程序的中断处继续往下执行了。”如果“RETI”的作用仅仅在于“把堆栈中保存着的地址取出送回PC”;那么我用指令“POPDPH”和“POPDPL”两条指令取代其做用不就可以达到同样的推出地址的效果么?这样可以解决由于只有进堆栈指令(硬件自动生成)没有出堆栈所导致的堆栈溢出错误,但是并不能解决文章开始所提到的“进不了中断”问题。这让我更加相信书上所介绍的关于指令“RETI”作用并不完全。经过查阅各种资料文献,我发现了个以往在介绍单片机硬件,以及寄存器上教材,老师,没有提及的“‘优先级生效’触发器“的概念。资料指出“根据8051的结构特点,其中断系统中含有两个不可寻址的“优先级生效”触发器。一个用于指出CPU是否正在执行高优先级的中断服务程序,这个触发器为1时,系统将屏蔽所有的中断请求;另一个则指出CPU是否正在执行低优先级中断服务程序,该触发器为1时,将阻止除高优先级以外的一切中断请求。由此可见,若要响应同级甚至是低级中断请求,必须使得该“优先级生效”触发器清零。但该触发器又是不可寻址的,所以无法用软件直接清零。”问题是不是在这里呢?而“优先级生效”触发器清零过程是怎样执行的呢?是在硬件自动执行的那么是在什么时候执行的呢?带着问题我去解决问题。假设我可以将程序满足跳出中断后跳到自己原来指定地址“ADR16”又满足执行指令“RETI”。经过反复思考我用“DEC SP”;“DEC SP”;“MOVDPTR,#ADR16”;“PUSHDPL”;“PUSHDPL”“PUSHDPH”四条指令代替,问题得到了解决。

  总结:中断指令“RETI”做为中断跳出指令除了将堆栈中保存着的地址取出,送回PC;使程序从主程序的中断处继续往下执行。的作用外还有将“优先级生效”触发器清零。自己做的程序也是出现了这个错误,由于对“优先级生效”触发器清零,导致第二次进不了中断(相当于同优先级申请)。

  后记:在解决这个问题时候我所用的知识是课本上的,而又不完全是课本上的。在这个过程中我用已学的知识解决了自己的问题,并进一步推出中断过程的一些新的知识,我认为新知识的学习有很大程度的要靠自己在已学过知识的基础上通过运用,总结,推导等过程获得新知识。着也是当代大学生运用知识,获取新知识的一种能力

ET 与RETI 基于51单片机中断跳出指令“RETI”浅议的更多相关文章

  1. 基于51单片机的CAN通讯协议C语言程序

      //-----------------------函数声明,变量定义-------------------------------------------------------- #includ ...

  2. 51单片机中断interrupt……using……

    51单片机中断细节的一些问题. interrupt0:外部中断0interrupt1:定时器中断0interrupt2:外部中断interrupt3:定时器中断1interrupt4:串口 using ...

  3. 基于51单片机IIC通信的PCF8591学习笔记

    引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...

  4. c语言编写51单片机中断程序,执行过程是怎样的?

    Q:c语言编写51单片机中断程序,执行过程是怎样的? 例如程序:#include<reg52.h>  void main(void)  {   EA=1;      //开放总中断   E ...

  5. 基于51单片机个LCD1602的万年历程序

    小白 第一次跟新博客 基于51单片机和LCD1602的万年历程序 可实现走时和调时功能 有简单的1602菜单制作 欢迎大家交流 LCD1602和51单片机的连接方法 RS = P3^5; //数据/命 ...

  6. (023) 关于51单片机的A5指令

    可看见一篇讲51单片机加密的文章这么讲: [加密方法:在A5后加一个二字节或三字节操作码,因为所有反汇编软件都不会反汇编A5指令,造成正常程序反汇编乱套,执行程序无问题仿制者就不能改变你的源程序.] ...

  7. 基于51单片机+DAC0832的信号发生器

    最近帮别人设计一个毕业设计,做一个多种信号发生器(四种波形:方波.三角波.锯齿波.梯形波),现在贴上来给大家参考,如果有错误的地方,望指出~ 下面先贴上仿真的电路图(仿真的软件是Protuse,上传一 ...

  8. 基于51单片机IIC通信的AT24C02学习笔记

    引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...

  9. 3.7 基于51单片机+MC20的路径显示【使用STC15W内核】

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...

随机推荐

  1. 2014.6.14模拟赛【bzoj1592】[Usaco2008 Feb]Making the Grade 路面修整

    Description FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了 ...

  2. 【POJ2777】Count Color(线段树)

    以下是题目大意: 有水平方向上很多块板子拼成的墙,一开始每一块都被涂成了颜色1,有C和P两个操作,代表的意思是:C X Y Z —— 从X到Y将板子涂成颜色ZP X Y    —— 查询X到Y的板子共 ...

  3. ext3中xtype属性汇总

    基本组件: xtype Class 描述 button Ext.Button 按钮 splitbutton Ext.SplitButton 带下拉菜单的按钮 cycle Ext.CycleButton ...

  4. Annotation(一)——注解开发介绍

    <p>在编程中,一直强调的一点就是注释的编写,注释的规范等等.尤其是越是核心,程序越复杂,逻辑越多的清空下,注释的编写对我们以后的阅读代码,维护软件起着至关重要的作用.一款软件有着好的注释 ...

  5. poj 1466 Girls and Boys(二分匹配之最大独立集)

    Description In the second year of the university somebody started a study on the romantic relations ...

  6. PYCHARM配置文件如何导入

    请到此下载,如下: http://share.weiyun.com/c00040649e85c4ab1dbc47a0fe9a0a7a 或者:http://files.cnblogs.com/files ...

  7. iPhone 5,6,6 plus 尺寸

  8. [RxJS] Combining Streams with CombineLatest

    Two streams often need to work together to produce the values you’ll need. This lesson shows how to ...

  9. [Redux] Extracting Presentational Components -- Todo, TodoList

    Code to be refactored: let nextTodoId = 0; class TodoApp extends Component { render() { const { todo ...

  10. C# winform带进度条的图片下载

    代码如下: public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private void ...