MCS-51中断程序执行完后,怎样重新从maim函数开始,而不是从中断点开始执行

MCS-51中断程序执行完后,怎样重新从maim函数开始,而不是从中断点开始执行呢?程序应该怎样写呢?

在原来中断点后直接写一个跳出,然后继续向下执行。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇文章:MCS-51单片机汇编语言程序设计 也许能够解决你的问题,你可以看下
  • 除此之外, 这篇博客: 第一章MCS-51单片机结构,单片机原理、接口及应用中的 三、存储器 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    分程序存储器和数据存储器,分片内和片外,从逻辑地址空间看,又可分为片内数据存储器、片外数据存储器、片内片外统一编址的程序存储器。

    引脚EA(上面一横)的接法决定了程序存储器0000H~0FFFH的4KB地址范围是在片内还是片外。为1时,片内0000H~0FFFH,片外1000H~FFFFH;为0时,0000H~FFFFH64KB都是片外。

    程序存储器:以PC作为地址指针,通过16位地址总线,可寻址64KB地址空间。

    程序存储器中的特殊地址:

    地址用途
    0000H复位操作后的程序入口
    0003H外部中断0服务程序入口
    000BH定时器0中断服务程序入口
    0013H外部中断1服务程序入口
    001BH定时器1中断服务程序入口
    0023H串行口中断服务程序入口

    由于两入口地址直接的存储空间有限,通常在这些入口地址开始的两三个地址单元中,放入一条转移类指令(跳转指令),使得相应程序跳转到指定的程序存储器区域。

    外部数据存储器:51单片机具有扩展64KB外部数据存储器RAM和I/O端口的能力,它们统一编址,使用相同的选通控制信号、相同的访问指令MOVX,以及相同的寄存器间接寻址。

    内部数据存储器:51单片机中只有128字节RAM,地址为00H~7FH,它和SFR的地址(80H~FFH)空间是连续的,而在增强型52子系列中有256字节RAM,高128字节RAM和SFR的地址是重合的,访问高128字节RAM采用寄存器间接寻址,访问SFR则采用直接寻址。

    在这里插入图片描述
    在这里插入图片描述
    前32个单元(00H~1FH)为寄存器区,共分4组,每组有8个8位寄存器R0~R7,R0和R1可作为间址寄存器使用。使用时,只能选其中一组寄存器,寄存器的选组由程序状态字PSW的RS1和RS0位定。一旦选中了一组寄存器,其它3组只能作为数据存储器使用,而不能作为寄存器使用。初始化或者复位时,自动选中0组。

    20H~2FH为位地址区,共16个单元,每个单元有8位,共128位,每位有一个位地址,范围为00H~7FH,该区既可位寻址,又可字节寻址。

    51单片机的堆栈设在内部RAM区,深度不大于128字节,初始化时SP指向07H。
    在这里插入图片描述


  • 以下回答来自chatgpt:

    答案:

    要实现中断程序执行完后重新从main函数开始执行,可以在中断程序的最后加上一条跳转指令,将程序计数器(PC)设置为main函数的起始地址。具体步骤如下:

    1. 首先在程序中定义中断服务程序,如下所示:

    ```c void InterruptServiceRoutine(void) interrupt 0 { // 中断服务程序代码 // ...

       // 跳转指令,将程序计数器(PC)设置为main函数起始地址
       // 假设main函数地址为0x1000
       __asm__("jmp 0x1000");
    

    } ```

    1. 在程序的初始化部分设置中断向量表,将中断号0对应的中断向量表项设置为中断服务程序的入口地址,如下所示:

    ```c // 定义中断向量表 // 中断号0对应的中断向量表项为0x0003 __code void (InterruptVectorTable[])(void) = {0x0003, / 其他中断向量表项 */};

    // 初始化中断向量表 void InitInterruptVectorTable(void) { int i; for (i = 0; i < sizeof(InterruptVectorTable) / sizeof(InterruptVectorTable[0]); i++) { ((unsigned char __xdata )(i * 3)) = (unsigned char)((unsigned long)InterruptVectorTable[i] & 0xFF); ((unsigned char __xdata )((i * 3) + 1)) = (unsigned char)(((unsigned long)InterruptVectorTable[i] >> 8) & 0xFF); ((unsigned char __xdata )((i * 3) + 2)) = (unsigned char)(((unsigned long)InterruptVectorTable[i] >> 16) & 0xFF); } }

    // 在main函数中调用InitInterruptVectorTable函数进行初始化 void main(void) { InitInterruptVectorTable();

       // 其他代码
       // ...
    

    } ```

    注意,在定义中断向量表时,要用__code指定其存储类型,以确保其被放在程序存储器(ROM)中,不会被修改。

    1. 在主程序中为中断使能位(IP)和总中断使能位(EA)赋初值,以确保中断可以正常工作,如下所示:

    ```c void main(void) { InitInterruptVectorTable();

       // 清除中断使能位(IP)和总中断使能位(EA)
       IP = 0x00;
       EA = 0;
    
       // 设置中断优先级和中断模式等其他配置
       // ...
    
       // 启用总中断使能位(EA)
       EA = 1;
    
       // 其他代码
       // ...
    

    } ```

    注意,在启用总中断使能位(EA)之前,需要先将中断使能位(IP)清零,以确保中断不会在设置完成之前被响应。

    1. 在中断服务程序中处理完中断后,加上跳转指令,将程序计数器(PC)设置为main函数的起始地址,如上所示。

    以上就是实现中断程序执行完后重新从main函数开始执行的方法。需要注意的是,在中断服务程序中,使用了__asm__关键字来直接插入汇编代码,实现了跳转指令的功能。同时,在设置中断向量表和初始化中断使能位(IP和EA)等操作时,也需要注意相应的细节。

    如果需要调试程序,在中断服务程序中加入调试代码,可以通过串口或其他方式将调试信息输出到终端上,以方便调试。在输出调试信息时,可以使用printf等常用的C库函数,也可以直接使用串口发送函数或其他适合的函数。具体实现方法可以参考MCS-51的相关资料和C语言的相关教程。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^