#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
#define tasknumsize 3
#define ramsize 128
uint idata wait[tasknumsize];
uchar taskrdy=0xff,curtask,nxttask;
void cswitch();
void waitdly(uint dly);
void taskA()
{
uchar temp,i;
while(1)
{
temp=0x01;
for(i=0;i<8;i++)
{
P1=temp;
temp=temp<<1;
waitdly(10);
}
}
}
void taskB()
{
while(1)
{
P2+=1;
waitdly(20);
}
}
void taskC()
{
while(1)
{
P3+=2;
waitdly(50);
}
}
void * const func[tasknumsize]={taskA,taskB,taskC};
uchar idata *stk[tasknumsize+1];
void initstarttask()
{
uchar idata *sspp,i;
sspp=(uchar idata *)SP+1; //需要指向堆栈的下一个空位处,51为满增堆栈.
stk[0]=(uchar idata *)SP+1;
stk[tasknumsize] = (uchar idata *)(ramsize);
*sspp++=((uint)(func[0]))%256;
*sspp=((uint)(func[0]))/256;
SP=(uchar)sspp;
sspp=(uchar idata *)(ramsize-1);
for(i=tasknumsize-1;i>0;i--)
{
*sspp--=((uint)(func[i]))/256;
stk[i]=sspp;
*sspp--=((uint)(func[i]))%256;
}
}
void inittimer0()
{
TMOD=0x01;//方式1,16位模式,不会自动清零。
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
EA=1;
ET0=1;
}
main()
{
inittimer0();
initstarttask(); //main函数中最后调用的这个函数是不会将函数的返回地址压入到堆栈中
}
void cswitch()
{
uchar idata *sp1,idata *sp2;
uchar temp,svsp,i;
temp=taskrdy;
for(nxttask=0;nxttask<tasknumsize;nxttask++)
{
if((temp & 0x80)!=0)
break;
temp=temp<<1;
}
if(nxttask==tasknumsize)
nxttask=0;
svsp=(uchar)SP;
sp1=(uchar *)SP+1;
sp2=stk[curtask+1];
temp=(uchar)stk[nxttask+1];
if(nxttask>curtask)
{
while(sp2!=(uchar idata *)temp) //堆栈空间变换
{
*sp1++=*sp2++;
}
SP=(uchar)sp1-1;
temp=stk[curtask+1]-(uchar idata *)svsp-1;
for(i=curtask+1;i<nxttask+1;i++)
{
stk[i]-=temp;
}
}
if(nxttask<curtask)
{
sp1--;sp2--;
while(sp1!=((uchar idata *)temp-1)) //堆栈空间变换
{
*sp2--=*sp1--;
}
SP=(uchar)stk[nxttask+1]-1;
temp=stk[curtask+1]-(uchar idata *)svsp-1;
for(i=nxttask+1;i<curtask+1;i++)
{
stk[i]+=temp;
}
}
if(nxttask==curtask)
SP=svsp;
curtask=nxttask;
}
void waitdly(uint dly)
{
wait[curtask]=dly;
while(wait[curtask]!=0)
{
taskrdy &= ~(0x80>>curtask);
cswitch();
}
}
void timer0() interrupt 1
{
uchar t;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
for(t=0;t<tasknumsize;t++)
{
if(wait[t]>0)
{
wait[t]--;
if(wait[t]==0)
taskrdy |= (0x80>>t);
}
}
}