⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 schedule.c

📁 avr单片机ATMega16对三相异步电机的智能控制源码
💻 C
字号:

#define SCHEDULE_GLOBAL
#include "schedule.h"


static void SCH_Updata(void);


// 在任一时刻要求的任务最大数目
#define SCH_MAX_TASKS (3)

// 任务队列
sTask SCH_tasks_G[SCH_MAX_TASKS];

// 错误代码
#define ERROR_SCH_TOO_MANY_TASKS (1)
#define ERROR_SCH_CANNOT_DELETE_TASK (2)

#define RETURN_NORMAL 0
#define RETURN_ERROR 1




/*---------------------------------------------------------*-
 * 函数名称: SCH_Dispatch_Tasks()
 * 入	 口: 
 * 出	 口:
 * 函数功能: 调度函数,当一个任务()需要运行时,此函数将运行它,
 * 
 * 说	 明: 这个函数必须被主循环(重复)调用 
-*---------------------------------------------------------*/

void SCH_Dispatch_Tasks(void)
{
	unsigned char Index;

	// 调度(运行)下一个任务(如果有任务就绪)
	for (Index=0; Index<SCH_MAX_TASKS; Index++)
	{
		if (SCH_tasks_G[Index].RunMe > 0)
		{
			// 运行任务
			(*SCH_tasks_G[Index].pTask)();
			
			// 复位 / 降低RunMe标志
			SCH_tasks_G[Index].RunMe -= 1;
			
			// 如果这个是'单次'任务,将它从队列中删除
			if (SCH_tasks_G[Index].Period == 0)
			{
				SCH_Delete_Task(Index);
			}
		}
	}
}



/*---------------------------------------------------------*-
 * 函数名称: SCH_Add_Task()
 * 入	 口: (*pFunction)任务指针,(DELAY)到第一次运行间隔时标,
 * 			 (PERIOD)每次运行的间隔时标
 *
 * 出	 口: 返回SCH_MAX_TASKS表示任务队列已满
 *			 返回(Index)=任务位置
 *
 * 函数功能: 用来添加任务到任务队列上,以保证它们在需要的时
 * 			 候被调用
 * 
 * 说	 明: 使任务函数每隔一定间隔或在用户的延迟之后执行.
-*---------------------------------------------------------*/

unsigned char SCH_Add_Task(void (*pFunction)(),	// 任务指针
							const unsigned int DELAY,	// 延迟Delay个时标后函数将第一次运行
							const unsigned int PERIOD)  // 连续的运行之间的间隔(时标)
{
	unsigned char Index = 0;	// 首先在队列中找到一个空隙

	while ((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
	{
		Index++;	
	}
	if (Index == SCH_MAX_TASKS)
	{
		return SCH_MAX_TASKS;  // 同时返回错误代码
	}

	// 如果能运行到这里,则说明任务队列中有空间
	SCH_tasks_G[Index].pTask = pFunction;
	SCH_tasks_G[Index].Delay = DELAY;
	SCH_tasks_G[Index].Period = PERIOD;
	SCH_tasks_G[Index].RunMe = 0;
	return Index;		// 返回任务的位置(以便以后删除)

}



/*---------------------------------------------------------*-
 * 函数名称: SCH_Delete_Task()
 * 入	 口: TASK_INDEX -任务索引.由SCH_Add_task()提供
 * 
 * 出	 口: 返回值: RETURN_ERROR(或)RETURN_NORMAL
 *		
 * 函数功能: 从调度器删除任务.
 * 
 * 说	 明: 请注意:并不是从存储器中删除相关的函数,仅仅是不再
 * 			 由调度器调用这个任务.
-*---------------------------------------------------------*/

uchar SCH_Delete_Task(const unsigned char TASK_INDEX)
{
	uchar Return_code;		//返回错误代码

	if (SCH_tasks_G[TASK_INDEX].pTask == 0)
	{	
		Return_code = RETURN_ERROR;	  
	}
	else
	{
		Return_code = RETURN_NORMAL;
	}

	// 删除任务
	SCH_tasks_G[TASK_INDEX].pTask = 0x00;
	SCH_tasks_G[TASK_INDEX].Delay = 0;
	SCH_tasks_G[TASK_INDEX].Period = 0;
	SCH_tasks_G[TASK_INDEX].RunMe = 0;

	return Return_code;
}


/*---------------------------------------------------------*-
 * 函数名称: SCH_Update()
 * 入	 口: 
 * 出	 口:
 * 函数功能: 在调度器的中断服务程序中运行
 * 
 * 说	 明: "刷新"函数,确定某个任务需要运行时,将这个任务的
 * 			 RunMe标志加1,然后该任务将由调度程序执行.
-*---------------------------------------------------------*/

static void SCH_Updata(void)
{
	unsigned char Index;
	for (Index=0; Index < SCH_MAX_TASKS; Index++)
	{
		// 检测这里是否有任务?
		if (SCH_tasks_G[Index].pTask != 0)
		{
			if (SCH_tasks_G[Index].Delay == 0)
			{
				SCH_tasks_G[Index].RunMe += 1;	// RunMer标志加1
				if (SCH_tasks_G[Index].Period != 0)
				{
					// 调度定期的任务再次运行
					SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;	
				}
			}
			else
			{
				// 还没有准备好运行,延迟减1
				SCH_tasks_G[Index].Delay -= 1;		
			}
		}	
	}
}


/*---------------------------------------------------------*-
 * 函数名称: SCH_Init_Timer2()
 * 入	 口: 
 * 出	 口:
 * 函数功能: 准备调度器数据结构并且设置定时器以所需的频率中断
 * 
 * 说	 明: 调度器初始化化函数,必须在使用调度器之前调用它
-*---------------------------------------------------------*/
void  InitTimer1(void)			//8MHz,10ms,64分频
{
 uchar i;
	
 for (i=0; i<SCH_MAX_TASKS; i++)
 {
  SCH_Delete_Task(i);
 }

 TCCR1B = 0x00; //stop
 TCNT1H = 0xFB; //setup
 TCNT1L = 0x1E;
 OCR1AH = 0x04;
 OCR1AL = 0xE2;
 OCR1BH = 0x04;
 OCR1BL = 0xE2;
 ICR1H  = 0x04;
 ICR1L  = 0xE2;
 TCCR1A = 0x00;
 TCCR1B = 0x03; //start Timer
} 


/*---------------------------------------------------------*-
 * 函数名称: SCH_Update_Server()
 * 入	 口: 
 * 出	 口:
 * 函数功能: 调度器的中断服务程序
 * 
 * 说	 明: "刷新"函数,确定某个任务需要运行时,将这个任务的
 * 			 RunMe标志加1,然后该任务将由调度程序执行.
-*---------------------------------------------------------*/
#pragma interrupt_handler SCH_Update_Server:9 //定时器溢出中断
void SCH_Update_Server(void)
{
  TCNT1H = 0xFB; //reload counter value
  TCNT1L = 0x1E; 
  
  TimeTick++;
  MotorDelayTime++;
  
  
  if(TimeTick%100 == 0)	  //1s喂狗
  {
   if(TimeTick == 200)TimeTick = 0;
   OutWdServer();  
  }
  
  
  SCH_Updata();

}


/*---------------------------------------------------------*-
 * 函数名称: SCH_Start()
 * 入	 口: 
 * 出	 口:
 * 函数功能: 通过允许中断来启动调度器
 * 
 * 说	 明: 在添加了所有定期的任务之后调用,从而使任务保持同步.
 *			 注意:应该只使能调度器中断
-*---------------------------------------------------------*/

void SCH_Start(void)
{
 SEI();
}





//**************END OF FILE*********************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -