• 51多任务系统,可以运行


     根据网上的资料,采用定时器2自动装载模式。每10ms进一次中断。

    图中可以看出,调用rtos_wait(100)后,PC=PC+3=0x0163,SP=SP+2;把PC值压栈,可以参考LCALL addr16这条汇编指令

    PC是16位,所以需要两个8位的空间,因此SP需要加2。

    /*
    使用keil4
    可运行8个任务
    任务从rtos_wait()处切换,在定时时间到后从定时中断中切换回来。
    
    使用定时器2作为系统始终
    */
    #include <regx52.H>
    #include <INTRINS.H>
    
    typedef unsigned char u8;
    typedef unsigned int u16;
    sbit LED1 = P2 ^ 0;
    sbit LED2 = P2 ^ 1;
    
    //两个宏定义是为了保护现场,不被定时中断打乱。
    //主要用于需要一次性运行完毕的代码中。
    #define OPEN_SYS_ISR() {EA=1;TR2=1;}
    #define CLOSE_SYS_ISR() {EA=0;TR2=0;TF2=0;}
    
    //#define TIMER_RELOAD()  {TL0=0xF0;TH0=0xD8;}	//使能T/C	  初始10ms
    #define MAX_TASKS 2 //任务槽最大个数.
    
    //任务堆栈.  PC指针为16位,需2个字节task_stack[][0]L  task_stack[][1]H。
    u8 idata task_stack[MAX_TASKS][2];
    //定时时间 (0-255)*10ms
    u8 idata task_time[MAX_TASKS];
    
    //当前活动任务号
    u8 task_id = 0;
    
    /*******************************************************************************
    * 函 数 名         : Timer2 Init
    * 函数功能		   : 定时器0初始化,用于系统时钟
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void timer2_init()
    {
        RCAP2H = (0xFFFF - 10000) / 256;
        RCAP2L = (0xFFFF - 10000) % 256;	//12MHz晶振下定10ms,自动重装
        TH2 = RCAP2H;
        TL2 = RCAP2L;					//定时器2赋初值
        T2CON = 0;					//配置定时器2控制寄存器,这里其实不用配置,T2CON上电默认就是0,这里赋值只是为了演示这个寄存器的配置
        T2MOD = 0;					//配置定时器2工作模式寄存器,这里其实不用配置,T2MOD上电默认就是0,这里赋值只是为了演示这个寄存器的配置
    
        IE = 0xA0;	//1010 0000开总中断,开外定时器2中断,可按位操作:EA=1; ET2=1;
        TR2 = 1;		//启动定时器2
    }
    
    
    void rtos_wait(u8 time)
    {
        static u8 i;
    
        task_time[task_id] = time;   	//保存当前任务时间
    
        //保存当前断点 并把SP=SP-2,任务切换到下一任务;
        task_stack[task_id][1] = *((u8 data*) SP);
        SP--;
    
        task_stack[task_id][0] = *((u8 data*) SP);
        SP--;
    
        //任务号设为最大,越过最大则回到0
        for (i = 0; i < MAX_TASKS; i++)
        {
            if (task_time[i] == 0)		//根据定时时间判断
            {
                task_id = i;
                break;
            }
        }
    }
    void task_sw()		 //任务时间是否到,任务时间到 实时切换回
    {
        //从把定时时间减1 ,找看哪个任务到	,任务时间到 实时切换回
        static u8 i;
        for (i = 0; i < MAX_TASKS; i++)
        {
            if (task_time[i])			//time[0] =  10    if(10)
            {
                task_time[i]--;			 //10--
                if (task_time[i] == 0)	//多个定时时间同时到,任务越靠后,越优先执行。
                {
                    task_id = i;			//当前任务号
    
                    //保存的PC指针调出来
                    SP++;
                    (*((u8 data*)(SP))) = task_stack[i][0];
                    SP++;
                    (*((u8 data*)(SP))) = task_stack[i][1] ;
                }
            }
        }
    }
    
    
    void tm2_isr() interrupt 5 //using 1
    {
    	//EA=0;
        //ET2=0;
        //TF2=0;
        //!!!注意!!!定时器2必须由软件对溢出标志位清零,TF2=0;硬件不能清零,
        //这里与定时器0和定时器1不同!!!
        CLOSE_SYS_ISR();
    
        task_sw();			//任务时间是否到,任务时间到,则实时切换回
    		
    	OPEN_SYS_ISR();
    }
    
    
    //****************************************************************示例
    void task_test()
    {
        while (1)
        {
            LED1 = ~LED1;
            rtos_wait(100);		 //1sec 执行完后,记录下一步地址,返回
        }
    }
    
    void task_test2()
    {
        while (1)
        {
            LED2 = ~LED2;
            rtos_wait(200);		//2sec 执行完后,记录下一步地址,返回
        }
    }
    
    void sys_init()
    {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
    
    void main()
    {
        sys_init();
        timer2_init();
        /* while(1)
        {
        	task_test();
        	task_test2();
        } */
        task_test();
        task_test2();
        while (1);
    }
    
  • 相关阅读:
    获取浏览器当前宽高
    获取当前页面一个 CSS 像素与一个物理像素之间的比率
    获取对象的所有属性,不管是否可遍历,不管是自身的还是原型链上的
    获取当前页面内所有框架窗口
    获取当前页面视口(viewport)宽高
    获取当前嵌入窗口所在的那个元素节点
    获取当前页面内框架窗口的数量
    获取窗口顶层对象
    获取当前窗口访问过的页面的数量
    获取`script`标签中的代码内容
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/12007463.html
Copyright © 2020-2023  润新知