keil c语言范例,简单实现 汇编及C语言混合 keil9.0工程源码

//----------------------------------------------------多任务处理  以rtos_开头

externunsigned char rtos_wait(unsigned char time);  //返回实际优先级 ,当所有高优先级都被占用时返回 0FFH,任务将被忽略。time为延时时间

externrtos_init(unsigned int count); //依据时间片轮转时间后,确定设置定时器count

void task0()

{

P0=0x0FF;

rtos_wait(100);

P0=0x0;

}

void task1()

{

while(1)

{

P1=~P1; //按位取反

rtos_wait(100);

}

}

void task2()

{

while(1)

{

P2=0x0FF;

rtos_wait(200);

P2=0x0;

rtos_wait(200);

}

}

voidmain()

{

P0=0;//初始化端口

P1=0;

P2=0;

rtos_init(0xD8F0); //操作系统初始化,根据单片机晶振,设置定时参数,比如10ms

task0(); //第一个任务。没有循环,任务结束就销毁。相当于200*10即2000ms即2s,在延时过程中运行其它的任务。

task1();  //第二个任务 在循环中任务就一直存在。不要以为这是死循环,进入这里后会自动切换到其它任务,时间到后又回来继续执行后面的。

task2();  //第三个任务,类似第二个任务

while(1);//主任务

}

rtos_c.asm

;********************************************

;RTOS用定时器0的多任务处理程序

;项目增加方式使用。

;程序不影响其它数据,目前程序的前后段不能进行参数传递 。 最多可以同时运行8个任务,

;执行时使用定时器0,定时时间根据初始化时的参数确定,一般为10mS。

;当指定优先级被占用时自动向高优先级调整,在R7中返回实际优先级,当所有高优先级都被占用时返回 0FFH,任务将被忽略。

;占用24H个内存单元。

;如果程序不可再入,需要设定 RWZT 的标志位。调用前先检查相应位。

;如果定时数设置过大,会引起一直在中断中,不能执行外部程序。如果任务执行时间过长,会引起堆栈溢出。

;18.432MHz,单时钟周期模式。不用任务单取反,输出频率 1.3MHz ,指令周期 384 nS 。速度是带系统的 100 倍。

;8个任务,只对管脚取反,T0=FEF0H,输出 2.8K 频率,为最高频率。执行周期不受任务影响。18.432MHz,单时钟周期模式。

;1个任务,只对管脚取反,T0=FFE1H,输出 12K 频率,为最高频率。执行周期受任务影响。每次调度时间为42US。

;*********************************************

;-------------------------------------------------------------示例程序

;externRTOS(unsigned char priority,time,unsigned int *add);

;externRTOS_INI(unsigned int count);

;externRTOS();

;sbitP1_0=P1^0;

;voiddeng(void)

;{

;P1_0=!P1_0;

;JMP(0,100,deng);

;}

;void main()

;{

;JMP(0,100,deng);

;while(1)

;{

;RTOS();

;}

;}

;***********************************************

NAMERTOS_C

?PR?RTOS?RTOS_CSEGMENTCODE

?DT?RTOS?RTOS_CSEGMENT DATA

?ID?RTOS?RTOS_CSEGMENT IDATA

PUBLICRTOS

PUBLIC_RTOS_WAIT

PUBLIC_RTOS_INIT

;---------------------------------------------

;BANBHEQU0A3H;版本号 101221

;定义数据地址

;----------------------------------------------

RSEG?DT?RTOS?RTOS_C

;RWZTEQU29H;任务状态,0为停止,1为正在执行

TL:DS 1;EQU30H;RTOS定时器值,C=FFFFH-ft

TH:DS 1;EQU31H;18.432MHz(12周期)=C400H

RWB:DS 1;EQU33H;任务表

RSEG?ID?RTOS?RTOS_C

RWDZ:DS 16

;EQU80H;任务地址

;EQU8FH

RWS:DS 8

;EQU90H;任务定时数

;EQU97H

;*********************************************

CSEG  AT   0BH         ;TO入口

JMP     RTOS

;*********************************************

RSEG?PR?RTOS?RTOS_C

_RTOS_INIT:;任务初始化1.定时器启动,2.RWB任务表置0

;-------------------------------------------- 在 R6 R7 中,设置定时值

;RTOS定时器值,C=FFFFH-ft,18.432MHz(12周期)=C400H,40MHz(12周期)=7DC9H

;定时器0定时程序,18.432MHz,10MS,方式1

ORL    TMOD,#01H   ;定时10MS

MOV    TL0,R7

MOV TL,R7

MOV    TH0,R6

MOV TH,R6

MOV RWB,#0

SETB   TR0

SETB   ET0

SETB   EA

RET                ;等待中断

;********************************************** 等待函数,优先级为最低 0 级,等待时间放入 R7 中

;目前函数不能传递参数

_RTOS_WAIT:MOVA,R7

MOVR5,A

MOVR7,#0

CALLYXJSZ ;优先级设置

CJNER7,#8,RWSZ  ;任务设置

MOVR7,#0FFH

RET

;---------------------------------------------任务设置

RWSZ:MOVA,R7;送任务数

ADDA,#RWS

MOVR0,A

MOVA,R5

MOV@R0,A

MOVA,R7;送地址

RLA

ADDA,#RWDZ

MOVR0,A

POPACC;跳转地址,在堆栈中

POPB

MOV@R0,B;低地址在低字节

INCR0

MOV@R0,A

MOVB,R7;设置任务列表

CLRA; 当前正在执行的程序如果被中断,并且中断中使用了此任务位,则此次任务将会丢失。

INCB;可以关中断来解决此问题。

SETBC

RWSZ2:RLCA

DJNZB,RWSZ2

ORLRWB,A

RET

;--------------------------

YXJSZ:MOVB,R7

INCB

MOVA,RWB

CLRC

YXJ2:RRCA

DJNZB,YXJ2

YXJ4:JNCYXJ3

RRCA

INCR7

JMPYXJ4

YXJ3:RET

;------------------------------- 中断程序

RTOS:MOV    TH0,TH

MOV    TL0,TL

JBPSW.3,RTOS1

JBPSW.4,RTOS2

PUSH0

PUSH1

PUSH2

PUSH3

PUSH4

PUSH5

PUSH6

PUSH7

JMPRTOS0

RTOS1:JBPSW.4,RTOS3

PUSH8

PUSH9

PUSH10

PUSH11

PUSH12

PUSH13

PUSH14

PUSH15

JMPRTOS0

RTOS2:

PUSH10H

PUSH11H

PUSH12H

PUSH13H

PUSH14H

PUSH15H

PUSH16H

PUSH17H

JMPRTOS0

RTOS3:PUSH18H

PUSH19H

PUSH1AH

PUSH1BH

PUSH1CH

PUSH1DH

PUSH1EH

PUSH1FH

RTOS0:PUSHPSW

PUSHACC

PUSHB

PUSHDPL

PUSHDPH

CALLRWDD0

POPDPH

POPDPL

POPB

POPACC

POPPSW

JBPSW.3,RTOS01

JBPSW.4,RTOS02

POP7

POP6

POP5

POP4

POP3

POP2

POP1

POP0

RETI

RTOS01:JBPSW.4,RTOS3

POP15

POP14

POP13

POP12

POP11

POP10

POP9

POP8

RETI

RTOS02:

POP17H

POP16H

POP15H

POP14H

POP13H

POP12H

POP11H

POP10H

RETI

RTOS03:POP1FH

POP1EH

POP1DH

POP1CH

POP1BH

POP1AH

POP19H

POP18H

RETI

;-----------------------------中断任务调度

RWDD0:MOVB,#7;任务号

MOVR0,#RWS+7

MOVR1,#0FFH;执行任务号

MOVA,RWB

JNZRWDD3

RET

RWDD3:CLRC

RLCA

JNCRWDD6

CJNE@R0,#0,RWDD2

RWDD4:CJNER1,#0FFH,RWDD6

MOVR1,B

RWDD6:DECR0

DECB

JNZRWDD3

CJNER1,#0FFH,RWCL

RET

RWDD2:DEC@R0

CJNE@R0,#0,RWDD6

JMPRWDD4

;---------------------------------

RWDD:MOVR1,#7

MOVR0,#RWS+7

MOVA,RWB

JNZRWDD03

RET

RWDD03:CLRC

RLCA

JNCRWDD06

CJNE@R0,#0,RWDD06

JMPRWCL

RWDD06:DECR0

DECR1

JNZRWDD03

RET

;--------------------------------------

RWCL:MOVDPTR,#RWDD

PUSHDPL

PUSHDPH

MOVA,R1

RLA

ADDA,#RWDZ

MOVR0,A

MOVA,@R0

PUSHACC;低地址在低字节

INCR0

MOVACC,@R0

PUSHACC

MOVA,#0FFH;清除任务列表  当前正在执行的程序如果在下一个中断到来时还未执行完, 它的优先级将变为最低优先级,

INCR1;可以加入一个执行标志 RWZT 来解决此问题。

CLRC

RWCL22:RLCA

DJNZR1,RWCL22

ANLRWB,A

RETI

;***********************************

END

C语言版切换示例

#include #define MAX_TASKS 2 //任务槽个数.必须和实际任务数一至

#define MAX_TASK_DEP 12 //最大栈深.最低不得少于2 个,保守值为12.

unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];//任务堆栈.

unsigned char idata task_sp[MAX_TASKS];

unsigned char task_id; //当前活动任务号

//任务切换函数(任务调度器)

void task_switch(){

task_sp[task_id] = SP;

if(++task_id == MAX_TASKS)

task_id = 0;

SP = task_sp[task_id];

}

//任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任

//务,则原任务丢失,但系统本身不会发生错误.

void task_load(unsigned int fn, unsigned char tid){

task_sp[tid] = task_stack[tid] + 1;

task_stack[tid][0] = (unsigned int)fn & 0xff; //低字节

task_stack[tid][1] = (unsigned int)fn >> 8;     //高字节

}

//从指定的任务开始运行任务调度.调用该宏后,将永不返回.

#define os_start(tid) {task_id = tid,SP = task_sp[tid];return;}

/*============================以下为测试代码==========================*/

void task1(){

static unsigned char i;

while(1){

i++;

task_switch();//编译后在这里打上断点

}

}

void task2(){

static unsigned char j;

while(1){

j+=2;

task_switch();//编译后在这里打上断点

}

}

void main(){

//这里装载了两个任务,因此在定义MAX_TASKS 时也必须定义为2

task_load(task1, 0);//将task1 函数装入0 号槽

task_load(task2, 1);//将task2 函数装入1 号槽

os_start(0);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值