MCS-51中断程序执行完后,怎样重新从maim函数开始,而不是从中断点开始执行呢?程序应该怎样写呢?
在原来中断点后直接写一个跳出,然后继续向下执行。
不知道你这个问题是否已经解决, 如果还没有解决的话:分程序存储器和数据存储器,分片内和片外,从逻辑地址空间看,又可分为片内数据存储器、片外数据存储器、片内片外统一编址的程序存储器。
引脚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。
答案:
要实现中断程序执行完后重新从main函数开始执行,可以在中断程序的最后加上一条跳转指令,将程序计数器(PC)设置为main函数的起始地址。具体步骤如下:
```c void InterruptServiceRoutine(void) interrupt 0 { // 中断服务程序代码 // ...
// 跳转指令,将程序计数器(PC)设置为main函数起始地址
// 假设main函数地址为0x1000
__asm__("jmp 0x1000");
} ```
```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)中,不会被修改。
```c void main(void) { InitInterruptVectorTable();
// 清除中断使能位(IP)和总中断使能位(EA)
IP = 0x00;
EA = 0;
// 设置中断优先级和中断模式等其他配置
// ...
// 启用总中断使能位(EA)
EA = 1;
// 其他代码
// ...
} ```
注意,在启用总中断使能位(EA)之前,需要先将中断使能位(IP)清零,以确保中断不会在设置完成之前被响应。
以上就是实现中断程序执行完后重新从main函数开始执行的方法。需要注意的是,在中断服务程序中,使用了__asm__关键字来直接插入汇编代码,实现了跳转指令的功能。同时,在设置中断向量表和初始化中断使能位(IP和EA)等操作时,也需要注意相应的细节。
如果需要调试程序,在中断服务程序中加入调试代码,可以通过串口或其他方式将调试信息输出到终端上,以方便调试。在输出调试信息时,可以使用printf等常用的C库函数,也可以直接使用串口发送函数或其他适合的函数。具体实现方法可以参考MCS-51的相关资料和C语言的相关教程。