关于51单片机的中断实现多任务的问题

时间:2022-03-14 19:50:35
   思路如下:进入中断保存断点地址,并且把栈内保存的断点地址修改,这样中断结束就跳转到修改后的相应位置,实现两个任务的切换。
  问题就是如何获得并修改断点地址,通过sp寄存器可以获得栈顶的地址,我想通过指针取地址就能得到断点地址,不知可行否。。以下代码是跳转测试,现象是先0x08对应的亮一个灯,随后0x80对应的灯一直亮着。。。0x0f没有出现,0x0855这个地址是通过keil查看汇编代码得到的地址,如下图,求问各位这样的方案可行吗,如果可行为什么代码没有跳到指定的位置(根据现象得出的)
#include <reg51.h>
unsigned char *sl;
unsigned char *sh;

void init()//初始化函数
{
TMOD=0x01;
TH0=0;
TL0=0; //初始值的设置
EA=1;//打开全局中断
ET0=1;//打开T0中断
TR0=1;
}  

void delayms (unsigned int a)
{
    unsigned int i,j;
for(i=0;i<a;i++)
for(j=0;j<124;j++);
}

void main()
{
    int m; 
for(m=0;m<5;m++)//-------------------------------------------------------预计是想跳到这,也就是这个灯会亮两次,然而并没有
{P0=0x08;delayms(500);}
P0=0x00;delayms(500);
 init(); 
for(m=0;m<5;m++)
{P0=0x80;delayms(500);}     
while(1){P0=0x0f;}



}
void T0time() interrupt 1
{
    sh=(unsigned char *)SP;
sl=sh-1;
*sh=0x08;
*sl=0x55;


    TH0=0;
    TL0=0; 

}  
关于51单片机的中断实现多任务的问题

5 个解决方案

#1


第一次提问,自己顶。。。。。

#2


看51的自带的例程,里面有个简易的多任务系统源代码

#3


  看了一下,那个源码,函数全是汇编。。而且也不算小了,只是简单的任务切换我想中断里十几行就够了,那个那么多代码完全找不到重点。。。能麻烦就提的问题说一下吗

#4


引用 2 楼 worldy 的回复:
看51的自带的例程,里面有个简易的多任务系统源代码
看了一下,那个源码,函数全是汇编。。而且也不算小了,只是简单的任务切换我想中断里十几行就够了,那个那么多代码完全找不到重点。。。能麻烦就提的问题说一下吗

#5


我已经解决了,上述方法其实有很多问题   比如栈顶不一定就是断点地址,而且切换后不仅要保证地址跳的正确,还要恢复现场(寄存器的值等),所以应该先分几块栈,比如双任务就在51单片机256字节ram中找两块作为栈,用两个变量保存两个栈顶值,在中断中保存上次运行任务的sp寄存器,再将sp赋另一个任务的sp值,实现切换,要注意的是中断前用到的寄存器(r0,r1,psw等)需要保存下来(也就是保存现场),c语言中断中用到的寄存器都会被压入栈内,因此我全部调用了一遍,确保寄存器都入栈,中断结束自动弹出(还原现场)

#1


第一次提问,自己顶。。。。。

#2


看51的自带的例程,里面有个简易的多任务系统源代码

#3


  看了一下,那个源码,函数全是汇编。。而且也不算小了,只是简单的任务切换我想中断里十几行就够了,那个那么多代码完全找不到重点。。。能麻烦就提的问题说一下吗

#4


引用 2 楼 worldy 的回复:
看51的自带的例程,里面有个简易的多任务系统源代码
看了一下,那个源码,函数全是汇编。。而且也不算小了,只是简单的任务切换我想中断里十几行就够了,那个那么多代码完全找不到重点。。。能麻烦就提的问题说一下吗

#5


我已经解决了,上述方法其实有很多问题   比如栈顶不一定就是断点地址,而且切换后不仅要保证地址跳的正确,还要恢复现场(寄存器的值等),所以应该先分几块栈,比如双任务就在51单片机256字节ram中找两块作为栈,用两个变量保存两个栈顶值,在中断中保存上次运行任务的sp寄存器,再将sp赋另一个任务的sp值,实现切换,要注意的是中断前用到的寄存器(r0,r1,psw等)需要保存下来(也就是保存现场),c语言中断中用到的寄存器都会被压入栈内,因此我全部调用了一遍,确保寄存器都入栈,中断结束自动弹出(还原现场)