初级会员
- 积分
- 87
- 金钱
- 87
- 注册时间
- 2015-4-29
- 在线时间
- 5 小时
|
楼主 |
发表于 2016-4-2 01:09:57
|
显示全部楼层
我们来用代码实现以上多任务程序设计思想。
首先是任务切换
while(1)
{
if(task_delay[0]==0) task0(); //task0 就绪,
if(task_delay[1]==0) task1(); //task1 就绪,
……
}
很显然,执行任务的条件是任务延时量 task_delay=0,那么任务延时量谁来控制呢?定时
器啊!定时器中断对任务延时量减一直到归零,标志任务就绪。当没有任务就绪时,任务切
换本身就是一个 Idle 任务。
void timer0(void) interrupt 1
{
if(task_delay[0]) task_delay[0]--;
if(task_delay[1]) task_delay[1]--;
……
}
例如 timer0 的中断节拍为 200Hz, task0_delay 初值为 10,则 task0()执行频度为
200/10=20Hz。
有了以上基础,我们来设计一个简单多任务程序,进一步深入理解这种程序设计思想。
任务要求:用单片机不同 IO 脚输出 1Hz, 5Hz, 10Hz, 20Hz 方波信号,这个程序很短,将
直接给出。
#include "reg51.h"
#define TIME_PER_SEC 200 //定义任务时钟频率, 200Hz
#define CLOCK 22118400 //定义时钟晶振,单位 Hz
#define MAX_TASK 4 //定义任务数量
extern void task0(void); //任务声明
extern void task1(void);
extern void task2(void);
extern void task3(void);
sbit f1Hz = P1^0; //端口定义
sbit f5Hz = P1^1;
sbit f10Hz = P1^2;
sbit f20Hz = P1^3;
unsigned char task_delay[4]; //任务延时变量定义
//定时器 0 初始化
void timer0_init(void)
{
unsigned char i;
for(i=0;i<MAX_TASK;i++) task_delay[i]=0; //任务延时量清零
TMOD = (TMOD & 0XF0) | 0X01; //定时器 0 工作在模式 1, 16Bit 定时器模
式
TH0 = 255-CLOCK/TIME_PER_SEC/12/256;
TL0 = 255-CLOCK/TIME_PER_SEC/12%256;
TR0 =1;
ET0 =1; //开启定时器和中断
}
// 系统 OS 定时中断服务
void timer0(void) interrupt 1
{
unsigned char i;
TH0 = 255-CLOCK/TIME_PER_SEC/12/256;
TL0 = 255-CLOCK/TIME_PER_SEC/12%256;
for(i=0;i<MAX_TASK;i++) if(task_delay[i]) task_delay[i]--;
//每节拍对任务延时变量减 1 ,减至 0 后,任务就绪。
}
/*main 主函数*/
void main(void)
{
timer0_init();
EA=1;//开总中断
while(1)
{
if(task_delay[0]==0) {task0(); task_delay[0] = TIME_PER_SEC/ 2;}
//要产生 1hz 信号,翻转周期就是 2Hz,以下同
if(task_delay[1]==0) {task1(); task_delay[1] = TIME_PER_SEC/10;}
//要产生 5hz 信号,翻转周期就是 10Hz,以下同
if(task_delay[2]==0) {task2(); task_delay[2] = TIME_PER_SEC/20;}
if(task_delay[3]==0) {task3(); task_delay[3] = TIME_PER_SEC/40;}
}
}
void task0(void)
{
f1Hz = !f1Hz;
}
void task1(void)
{
f5Hz = !f5Hz;
}
void task2(void)
{
f10Hz = !f10Hz;
}
void task3(void)
{
f20Hz = !f20Hz;
} |
|