|
本帖最后由 Tliang 于 2012-7-24 15:07 编辑
- #include<avr/io.h>
- #include"Task.h"
- #include<avr/interrupt.h>
- #define Task_Max 5 //任务数
- #define Stack_Top 12 //任务堆栈空间
- typedef struct Task_Value
- {
- uint8 p; //任务堆栈指针
- uint16 delay; //任务延时
- uint8 State; //任务状态
- }Task;
- static Task Task_Buf[Task_Max]; //任务空间
- static uint8 Task_SP[Task_Max][Stack_Top]; //任务堆栈空间
- static uint8 Task_Run_ID; //正在运行任务ID
- void AddTask(uint16 TaskName, uint16 TaskDelay, uint8 TaskID)
- {
- Task_Buf[TaskID].p = (uint16)Task_SP[TaskID] + 9;
- //AVR单片机SP堆栈方向是由上往下生长的,执行RET的时候SP将加1,所以要比实际地址小1
- Task_SP[TaskID][10] = (uint8)(TaskName >> 8); //地址高8位
- Task_SP[TaskID][11] = (uint8)(TaskName & 0xff); //地址低8位
- Task_Buf[TaskID].delay = TaskDelay;
- Task_Buf[TaskID].State = 0;
- }
- void Task_Delay(uint16 Del)
- {
- uint8 Temp = 0;
- Task_Buf[Task_Run_ID].p = SP; //保存当前堆栈
- Task_Buf[Task_Run_ID].delay = Del; //设置延时
- Task_Buf[Task_Run_ID].State -= 1; //将状态置0
- for(Temp = 0;Temp < Task_Max - 1;Temp++)
- {
- if(Task_Buf[Temp].State == 1) //如果有任务处于就绪状态,执行.
- {
- break;
- }
- }
- SP = Task_Buf[Temp].p; //将任务堆栈地址赋给SP堆栈地址
- Task_Run_ID = Temp; //运行改变ID
- }
- ISR(TIM0_OVF_vect)
- {
- uint8 Index = 0;
- uint8 IDBuf = Task_Run_ID; //保存当前运行任务的ID
- uint8 Task_Run_SP = Task_Buf[Task_Run_ID].p - SP;
- //任务堆栈指针减去当前堆栈指针得到中断所使用掉的堆栈
- TCNT0 = 0x00;
- Task_Buf[Task_Run_ID].p = SP + Task_Run_SP;
- //当前堆栈指针加上中断所使用掉的堆栈数得到中断前堆栈指针,保存
- for(Index = 0;Index < Task_Max;Index++)
- {
- if(Task_Buf[Index].p != 0)
- {
- if((Task_Buf[Index].delay == 0) && (Task_Buf[Index].State == 0))
- {
- //如果任务延时时间到,将就绪置位
- Task_Buf[Index].State = 1;
- if(Index < IDBuf)
- {
- IDBuf = Index; //如果当前运行任务优先级低于就绪任务则切换
- }
- }
- else if((Task_Buf[Index].delay != 0) && (Task_Buf[Index].State == 0))
- {
- Task_Buf[Index].delay -= 1; //时间未到,时间标志减1
- }
- }
- }
- //将运行任务指针减去中断所用堆栈数得到中断返回前的堆栈指针,中断返回将加上
- //中断所用掉的堆栈数量,就得到将运行任务的实际堆栈指针
- SP = Task_Buf[IDBuf].p - Task_Run_SP;
- Task_Run_ID = IDBuf; //改变当前运行任务ID
- }
- void Task_Kong(void)
- {
- while(1); //当没有任务执行的时候就停留在此处,可以加入CPU空闲计算
- }
- void Time0_Task_Start(void)
- {
- AddTask((uint16)Task_Kong, 0, Task_Max - 1); //添加空任务
- TCCR0A = 0x00;
- TCCR0B = 0x03;
- TCNT0 = 0x00;
- TIMSK0 |= 0x01;
- sei();
- Task_Run_ID = Task_Max - 1; //开始运行运行空任务,可用形参指定运行那个任务
- SP = Task_Buf[Task_Run_ID].p; //任务开始运行
- }
复制代码 这段程序在Task_Delay这个函数中Task_Buf[Task_Run_ID].State -= 1不知道为什么不能直接给0。直接给0并未将它清0。所以这里就写减1了。请各位大侠帮忙看看原因。
还有小弟不明白任务间如何通讯。那位大侠能否给小弟我讲解一下消息机制和邮箱队列怎么构成的,多谢了。
这段程序是ATtiny24的程序。在5楼我打包了一个ATmega8的测试程序。有Proteus仿真。 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|